等待数组完成填充,然后再调用angular

时间:2019-03-21 16:05:04

标签: angular typescript

这是我的代码,我从一个空数组开始,想要调用一个对填充后的数组做一些工作的服务。我使用对服务的两次调用来填充数组,这些服务调用一个API来接收要插入到数组中的元素。

我无法弄清楚如何等待最后一个服务调用,直到阵列被填充后再执行。我认为我要等待两个单独的服务调用,以及它们都具有forEach循环这一事实使这比以前要难。有任何想法吗?

const subscribers: ISubscriber[] = [];

this.selectedChildren.forEach(child => {
    this.serviceA.getSubscribers(child.id).subscribe( (subs: ISubscriber[]) => {
        subs.forEach(s => {
            subscribers.push(s);
        });
    });
});

this.selectedSubscribers.forEach(sub => {
    this.serviceB.getSubscriber(sub.subscriberId).subscribe( (sub: ISubscriber) => {
        subscribers.push(sub);
    });
});

// subscribers is always empty when this call is made 
// since above code hasn't finished executing
this.serviceC.processSubscribers(subscribers).subscribe( sub => {
    this.toastr.success('Success!');
});

异步/等待尝试不起作用:

async doSomething(){
    const subscribers: ISubscriber[] = [];

    await this.selectedChildren.forEach(async child => {
        await this.serviceA.getSubscribers(child.id).subscribe( (subs: ISubscriber[]) => {
            subs.forEach(s => {
                subscribers.push(s);
            });
        });
    });

    await this.selectedSubscribers.forEach(async sub => {
        await this.serviceB.getSubscriber(sub.subscriberId).subscribe( (sub: ISubscriber) => {
            subscribers.push(sub);
        });
    });

    // subscribers is always empty when this call is made 
    // since above code hasn't finished executing
    this.serviceC.processSubscribers(this.id, subscribers).subscribe( id => {
        this.toastr.success('Success!');
    });
}

承诺。所有无效的尝试:

doSomething(){
    const subscribers: ISubscriber[] = [];
    const promises = [];

    this.selectedChildren.forEach(child => {
        promises.push(this.serviceA.getSubscribers(child.id).subscribe( (subs: ISubscriber[]) => {
            subs.forEach(s => {
                subscribers.push(s);
            });
        }));
    });

    this.selectedSubscribers.forEach(sub => {
        promises.push(this.serviceB.getSubscriber(sub.subscriberId).subscribe( (sub: ISubscriber) => {
            subscribers.push(sub);
        }));
    });

    // subscribers is always empty when this call is made 
    // since above code hasn't finished executing
    Promise.all(promises).then( a => {
        this.serviceC.processSubscribers(this.id, subscribers).subscribe( id => {
            this.toastr.success('Success!');
        });
    });
}

2 个答案:

答案 0 :(得分:3)

使用rxjs运算符的解决方案:

  • 请记住,您在可观察链中应该只有 1个订阅
  • combineLatest 等同于Promise.all
  • 切换图允许您将serviceA和serviceB的结果类型更改为serviceC
    const subscribers: ISubscriber[] = [];
    const subscriberObservables = [];

    // First you add all async calls into an array
    this.selectedChildren.forEach(child => {
        subscriberObservables.push(this.serviceA.getSubscribers(child.id));
    });

    this.selectedSubscribers.forEach(sub => {
        subscriberObservables.push(this.serviceB.getSubscriber(sub.subscriberId));
    });

    // then you run all of them in parallel
    combineLatest(subscriberObservables)
      .pipe(
        map((arrayOfArrays:ISubscriber[][]) => arrayOfArrays.flat()),
        switchMap( (subs: ISubscriber[]) => this.serviceC.processSubscribers(subscribers))
      )
      .subscribe( sub => {
          this.toastr.success('Success!');
      });

答案 1 :(得分:0)

这是我发现的使用诺言最终解决的解决方案:

doSomething(){
    const subscribers: ISubscriber[] = [];
    const promises = [];

    this.selectedChildren.forEach(child => {
        promises.push(this.serviceA.getSubscribers(child.id).toPromise().then( (subs: ISubscriber[]) => {
            subs.forEach(s => {
                subscribers.push(s);
            });
        }));
    });

    this.selectedSubscribers.forEach(sub => {
        promises.push(this.serviceB.getSubscriber(sub.subscriberId).toPromise().then( (sub: ISubscriber) => {
            subscribers.push(sub);
        }));
    });

    // subscribers is always empty when this call is made 
    // since above code hasn't finished executing
    Promise.all(promises).then( a => {
        this.serviceC.processSubscribers(this.id, subscribers).subscribe( id => {
            this.toastr.success('Success!');
        });
    });
}