简体   繁体   English

等待Angular 4中的订阅和承诺

[英]Wait for a Subscription and a Promise in Angular 4

I'm new to Angular 4, so I accept that I may be better off changing my approach. 我是Angular 4的新手,所以我接受我改变方法可能会更好。

What I have is this: 我有的是这个:

ngOnInit() {
    this.route.paramMap
        .switchMap((params: ParamMap) => {
            var id = +params.get('id');
            return this.service.getOne(id);
        }).subscribe(data => {
            if (data.clientID === 0) {
                data.clientID = +this.route.snapshot.queryParams["parentId"];
            }
            this.model = data;
        },); // Subscription

    this.lookupService.getList("clients").then(data => {
        this.clients = data;
    }); // Promise
}

On the client-side, I need to make another server call, but only when I have data from both of the calls above. 在客户端,我需要进行另一次服务器调用,但只有当我有来自上述两个调用的数据时。 In other words, I need the Subscription to complete (well, not complete but set the value) and the Promise to complete. 换句话说,我需要Subscription完成(好,不完整但设置值)和Promise完成。

Is there something like a Promise.all that would work to also ensure this.model has been set in the Subscription call? 是否有像Promise.all这样的Promise.all ,以确保在Subscription调用中设置this.model

EDIT: I could run these in series, but for performance reasons, I want to run them in parallel. 编辑:我可以连续运行这些,但出于性能原因,我想并行运行它们。

EDIT 2: The Promise was intended to load lookup data to populate a dropdown only once. 编辑2: Promise旨在加载查找数据以仅填充一次下拉列表。 The Subscription was intended to change the main model on each change of "id" in the URL . Subscription旨在更改URL中“id”每次更改的主模型。

  1. Use .zip() on the promise and the model-fetching observable. 在promise和模型提取observable上使用.zip() It will output an array of results that you can use to populate local class properties. 它将输出一组结果,您可以使用这些结果填充本地类属性。 At this point you can call your 3rd function (the local filter). 此时,您可以调用第3个函数(本地过滤器)。 Once the promise completes, so will .zip , so this chain has only one output. 一旦承诺完成, .zip也将如此,因此这个链只有一个输出。

  2. Once .zip() completes, listen to new route parameters and fetch corresponding models. 一旦.zip()完成,就要收听新的路由参数并获取相应的模型。 As they arrive, set your local class property and run your local filter 当它们到达时,设置本地类属性并运行本地过滤器

  3. Subscribe to trigger the whole chain. 订阅触发整个链。

     ngOnInit(){ // Will run getOne() with every new parameter let getModelForParam = this.route.paramMap.switchMap( params => this.service.getOne(+params.get('id')) ).share(); // Zip will wait for both below to produce, then output an array of results // and complete (since getList() promise completes after one call) Observable.zip( this.lookupService.getList('clients'), getModelForParam ).do(results => { // capture results in order of .zip() arguments this.clients = results[0]; this.model = results[1]; this.localFilter();// call the filter }).concat( // this part executes once .zip() completes getModelForParam // continue fetching models for new params ).subscribe(model => { this.model = model; this.localFilter(); }) } 

Live demo 现场演示

You can use Observable.forkJoin , which is equivalent to Promise.all . 您可以使用Observable.forkJoin ,它等同于Promise.all

Observable.forkJoin(this.route.paramMap
        .switchMap((params: ParamMap) => {
            var id = +params.get('id');
            return this.service.getOne(id);
        }), Observable.fromPromise(this.lookupService.getList("clients")))
        .subscribe((arrayOfResults) => {
             [firstCallResult, secondCallResult] = arrayOfResults;
             this.model = firstCallResult;
        });

EDIT: 编辑:

To fulfill the part about updating parameters, we can use the Observable.combineLatest operator: 为了完成有关更新参数的部分,我们可以使用Observable.combineLatest运算符:

About Observable.combineLatest 关于Observable.combineLatest

Since it emits whenever one of the source observables emits, the subscribe block will be executed. 由于每当其中一个源可观察对象发出时它就会发出,因此将执行订阅块。 Since the other observable is from a promise it will complete and not emit more values so this.lookupService.getList() will not be called again. 由于另一个observable来自promise它将完成而不会发出更多值,因此不会再调用this.lookupService.getList()。

Observable.combineLatest(this.route.paramMap
            .switchMap((params: ParamMap) => {
                var id = +params.get('id');
                return this.service.getOne(id);
            }), Observable.fromPromise(this.lookupService.getList("clients")))
            .subscribe((arrayOfResults) => {
                 [firstCallResult, secondCallResult] = arrayOfResults;
                 this.model = firstCallResult;
                 // do whatever else is needed
            });

You can do something like 你可以做点什么

ngOnInit() {
  this.lookupService.getList("clients").then(data => {
    this.clients = data;
    this.route.paramMap
    .switchMap((params: ParamMap) => {
        var id = +params.get('id');
        return this.service.getOne(id);
    }).subscribe(data => {
        if (data.clientID === 0) {
            data.clientID = +this.route.snapshot.queryParams["parentId"];
        }
        this.model = data;
==>Call ur method here!!!
    },); /

}); // Promise

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM