代码之家  ›  专栏  ›  技术社区  ›  awmleer

如何将可观察对象转换为行为主体?

  •  0
  • awmleer  · 技术社区  · 6 年前

    我想把一个可观察的东西变成行为主体。这样地:

    a$ = new Observable()
    b$ = BehaviorSubject.create(new BehaviorSubject(123), a$)
    // 🔴
    

    我也尝试过:

    a$ = new Observable()
    b$ = new BehaviorSubject(a$, 123)
    // 🔴
    

    a$ = new Observable()
    b$ = a$.asBehaviorSubject(123)
    // 🔴
    

    以及:

    a$ = new Observable()
    b$ = a$.pipe(
      toBehaviorSubject(123)
    )
    // 🔴
    

    但这些都不管用。现在我必须这样实施:

    a$ = new Observable()
    b$ = new BehaviorSubject(123)
    a$.subscribe(b$)
    // 🔵
    

    这在课堂上会有点难看:

    class Foo() {
      a$ = new Observable() // Actually, a$ is more complicated than this.
      b$ = new BehaviorSubject(123)
    
      constructor() {
        this.a$.subscribe(this.b$)
      }
    }
    

    那么,有没有一种更简单的方法不用类构造函数就可以将一个可观察对象转换成行为主体呢?


    这是我的真实案例:

    export class Foo {
      autoCompleteItems$ = new BehaviorSubject<string[]>(null)
      autoCompleteSelected$ = new BehaviorSubject<number>(-1)
      autoCompleteSelectedChange$ = new Subject<'up'|'down'>()
    
      constructor() {
        this.autoCompleteItems$.pipe(
          switchMap((items) => {
            if (!items) return EMPTY
            return this.autoCompleteSelectedChange$.pipe(
              startWith('down'),
              scan<any, number>((acc, value) => {
                if (value === 'up') {
                  if (acc <= 0) {
                    return items.length - 1
                  } else {
                    return acc - 1
                  }
                } else {
                  if (acc >= items.length - 1) {
                    return 0
                  } else {
                    return acc + 1
                  }
                }
              }, -1)
            )
          })
        ).subscribe(this.autoCompleteSelected$)
      }
    
      doAutoComplete = () => {
        const item = this.autoCompleteItems$.value[this.autoCompleteSelected$.value]
        // do something with `item`
      }
    }
    
    2 回复  |  直到 6 年前
        1
  •  36
  •   yaya    4 年前

    不需要转换。

    obs.subscribe(sub)

    例子:

    var obs = new rxjs.Observable((s) => {setTimeout(()=>{s.next([1])} , 500)}) //observable
    var sub = new rxjs.BehaviorSubject([0]) //create subject
    obs.subscribe(sub) //<----- HERE ----- attach observable to subject
    setTimeout(() => {sub.next([2, 3])}, 1500) //subject updated
    sub.subscribe(a => console.log(a)) //subscribe to subject
    

    注意 : obs.订阅(分) 相当于:

    obs.subscribe({
      next: v => sub.next(v),
      error: v => sub.error(v),
      complete: () => sub.complete()
    })
    
        2
  •  12
  •   tmuecksch    5 年前

    这就是我如何将我的观察对象转换为行为主体:

    import { Observable, BehaviorSubject } from 'rxjs';
    
    export function convertObservableToBehaviorSubject<T>(observable: Observable<T>, initValue: T): BehaviorSubject<T> {
        const subject = new BehaviorSubject(initValue);
    
        observable.subscribe({
            complete: () => subject.complete(),
            error: x => subject.error(x),
            next: x => subject.next(x)
        });
    
        return subject;
    }
    
        3
  •  0
  •   an-angular-dev    4 年前

    经过一番研究,我决定使用helper方法。但要小心使用(例如,确保您使用的是 Observable ,派生自 BehaviorSubject ,否则你会收到 undefined

    import { Observable, Subscription } from 'rxjs';
    
    export function getObsValue<T>(observable: Observable<T>): T {
        let value: T;
        const subscription: Subscription = observable.subscribe(
            (v: T) => {
                value = v;
            },
            () => {
            },
        );
        subscription.unsubscribe();
        return value!;
    }
    

    你可以这样写,以确保你处理 未定义

    import { Observable, Subscription } from 'rxjs';
    
    export function getObsValue<T>(observable: Observable<T>): T | undefined {
        let value: T | undefined;
        const subscription: Subscription = observable.subscribe(
            (v: T) => {
                value = v;
            },
            () => {
            },
        );
        subscription.unsubscribe();
        return value!;
    }
    
        4
  •  -1
  •   awmleer    6 年前

    我也很关心用例。但这里有一个解决方案,只要你留下反馈意见,就可以随意投票否决。自 BehaviourSubject 还有其他的吗 Subject Observables

    import { BehaviorSubject, from } from 'rxjs'; 
    import { map, mergeMap } from 'rxjs/operators';
    
    
    const source$ = from([1,2,3,4,5,6,7,8,9]);
    const bs = new BehaviorSubject('start')
        .pipe(
            mergeMap(() => source$)
        );
    
    bs.subscribe(console.log);