结合主题时,模板中未更新的异步管道可观察到

时间:2019-02-04 04:22:47

标签: angular rxjs behaviorsubject subject

我有一个组件,可通过异步管道将可观察的值(test $)打印到模板。

需要基于组件的输入来初始化组件属性,因此我将其值分配给ngOnInit中的服务(test $)发出的可观察对象。 服务初始化时,服务公开的可观察对象将分配给主题组合。 该值未打印在模板中。  Stackblitz

如果我将合并的主题定义为BehaviorSubject,则会将新值通知模板。

我认为这与冷/热观测物有关。据我了解,如果您订阅一个BehaviorSubject,即使您在发出一个值之后进行订阅,您也将始终获得最新的值,但是对于可观察到的可观测对象(作为Subject),您需要在该值发出之前进行订阅才能被通知

那么,如果订阅发生在主题发出值之前,为什么模板不更新?我的理由是,订阅在模板渲染后进行,该模板位于ngOnInit中。直到完成此步骤之后,主体才发出它们的值。

组件

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  @Input() initialValue: number;
  result$: Observable<number>;

  constructor(private service: TestService) {

  }

  ngOnInit() {
    console.log('component init');
this.result$ = this.service.result$;
// Get data based on inputs
this.service.initTransformedValue(this.initialValue);
  }


}

服务

@Injectable()
export class TestService {


  result$: Observable<number>;
  otherValue$: Observable<number>;
  transformedValue$: Observable<number>;

  constructor() {
    console.log('service constructor');
    this.init();
  }

  init(){
    this.result$ = combineLatest(
      this.transformedValue$,
      this.otherValue$
    ).pipe(map(([first, second]) => {
        console.log('have combined value');
        return first + second;
    })
    );
  }

  initTransformedValue(initialValue) {
    // Use timeout to simulate HTTP calls
    setTimeout(() => {
      console.log('service. emit transformedValue value');
      this.transformedValue$ = of(initialValue * 2);
    }, 1000);

setTimeout(() => {
      console.log('service. emit otherValue value');
      this.otherValue$ = of(initialValue * 4);
    }, 1200);



  }

}

模板

<p>{{result$ | async}}</p>

1 个答案:

答案 0 :(得分:0)

您要创建带有的新可观察对象,您需要使当前可观察对象发出新值。

https://stackblitz.com/edit/angular-fta9h1

永远不要将一个可观察对象与另一个可观察对象重新分配,应该通过调用next使现有的可观察对象发出,主题和行为主体可以发出。

const { of, BehaviorSubject } = rxjs;

let obs = of('of initial value');

obs.subscribe(val => { console.log(val); });

// This is a new observable and will not effect the subscription to a different obsevable
obs = of('of new value');

const bs = new BehaviorSubject('BehaviorSubject initial value');

bs.subscribe(val => { console.log(val); });

// This emits a new value on the same observable
bs.next('BehaviorSubject new value');
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>