在 foreach 中等待几个可观察的 rxjs 直到完成执行另一个

Posted

技术标签:

【中文标题】在 foreach 中等待几个可观察的 rxjs 直到完成执行另一个【英文标题】:Wait for several rxjs observable inside foreach till finished to execute an another 【发布时间】:2020-02-25 20:57:15 【问题描述】: 我想循环检查 checked_checkboxes 值。 foreach 我想做一个 POST 请求。 然后,当 foreach 中的所有 POST 请求完成后,我想获取刚刚查询的数据。

问题:

我的 get 函数与我的 post 函数是分开的,所以 post 查询没有完成,它会执行 get,所以它的结果是一个空的 get,因为帖子还没有发布。

解决方案:

将 observables 添加到数组中,然后将它们放入 foreach 末尾的 forkJoin 中。

我所看到的可能:

将 observable 转化为 promise 然后使用 async await,不太适应这个 可以使用 forkJoin 操作符来执行一些 observables 并等待它们全部完成。

我的 API 服务返回 RxJs observables,我在 Angular 8 中,这是两个函数: 首先是 AddVacation() 将发布一些数据,然后 getAgentsInSfihtDispo() 将获取发布的数据。

addVacation() 
    let counter = 0;
    const shift_id = this.selectedShiftForMaincouranteModify;
    const shift_date = this.modifyForm.value.dateDeb.format('YYYY-MM-DD');
    this.api.sendGetRequest("/api/shift_dates/" + shift_date, true, null, null)
        .subscribe((data) => 
            this.agents_dispo_checked.forEach((agent) => 
                const agent_id = agent.id;
                if (data) 
                    this.api.sendPostRequest('/api/shift_dos', true, null,
                         shift_id: shift_id, shift_date: shift_date, agent_id: agent_id )
                        .subscribe();
                 else 
                    this.api.sendPostRequest("/api/shift_dates", true, null,  date: shift_date )
                        .subscribe((data3) => 
                            if (data3.error === "L'association existe deja dans la base de données") 
                                this.api.sendPostRequest('/api/shift_dos', true, null,
                                     shift_id: shift_id, shift_date: shift_date, agent_id: agent_id )
                                    .subscribe();
                             else 
                                this.api.sendPostRequest('/api/shift_dos', true, null,
                                     shift_id: shift_id, shift_date: data3.date, agent_id: agent_id )
                                    .subscribe();
                            
                        );
                
                counter++;
            );
            if (this.agents_dispo_checked.length === counter) 
                this.isOpenSaisieVacation = false;
                this.getAgentsInShiftAndDispo();
            
        ,
    (err) => console.error(err));


getAgentsInShiftAndDispo() 
    this.agentsInShift = [];
    this.agents_dispo = [];
    this.agentsInShiftSelectedFormArray.clear();
    this.agentsDispoFormArray.clear();
    if (this.selectedShiftForMaincouranteModify !== 0 &&
        (this.modifyForm.controls.dateDeb.value !== "" || this.modifyForm.controls.dateDeb.value !== null || this.modifyForm.controls.dateDeb.value !== undefined)) 
        const shift_id = this.selectedShiftForMaincouranteModify;
        const goodFormatDate = this.modifyForm.value.dateDeb.format('YYYY-MM-DD');
        this.api.sendGetRequest('/api/shift_dos/byShiftAndDate/' + shift_id + "/" + goodFormatDate, true, null, null)
            .subscribe((data) => 
                if (data) 
                    data.forEach((item) => 
                        this.agentsInShift.push(item.agent);
                    );
                
            , (err) => console.error(err),
            () => 
                this.agentsInShift.map((o, i) => 
                    const control = new FormControl(true); // if first item set to true, else false
                    this.agentsInShiftSelectedFormArray.push(control);
                );
                const difference = this.agentsMaintenance.filter((obj) => 
                    return !this.agentsInShift.some((obj2) => 
                        return obj.id === obj2.id;
                    );
                );
                this.agents_dispo = difference;
                this.agents_dispo.map((o, i) => 
                    const control = new FormControl(false); // if first item set to true, else false
                    this.agentsDispoFormArray.push(control);
                );
            );
    

在此先感谢您带领我进入 RxJs 运营商的广阔世界。

【问题讨论】:

您的“我所看到的可能”是对的。我理解您对 async-await 的疑虑。但我希望您不要认为每次迭代都需要这样做。只需执行 Promise.all()。你对 forkJoin 有什么问题? 嗯,有些人对我说 observable 是处理 http 请求的更好方法,所以我更喜欢使用它们而不是 promise。 【参考方案1】:

您必须将所有 Observables 推入一个数组,并使用 forkJoin。

private observables = [];

addVacation() 
    let counter = 0;
    const shift_id = this.selectedShiftForMaincouranteModify;
    const shift_date = this.modifyForm.value.dateDeb.format('YYYY-MM-DD');
    this.api.sendGetRequest("/api/shift_dates/" + shift_date, true, null, null)
        .subscribe((data) => 
            this.agents_dispo_checked.forEach((agent) => 
                const agent_id = agent.id;
                if (data) 
                    this.observables.push(this.api.sendPostRequest('/api/shift_dos', true, null,
                         shift_id: shift_id, shift_date: shift_date, agent_id: agent_id ));
                 else 
                    this.observables.push(this.api.sendPostRequest("/api/shift_dates", true, null,  date: shift_date )
                        .subscribe((data3) => 
                            if (data3.error === "L'association existe deja dans la base de données") 
                                this.observables.push(this.api.sendPostRequest('/api/shift_dos', true, null,
                                     shift_id: shift_id, shift_date: shift_date, agent_id: agent_id ));
                             else 
                                this.observables.push(this.api.sendPostRequest('/api/shift_dos', true, null,
                                     shift_id: shift_id, shift_date: data3.date, agent_id: agent_id ));
                            
                        );
                
                counter++;
            );
            if (this.agents_dispo_checked.length === counter) 
                this.isOpenSaisieVacation = false;
                forkJoin(this.observables)
                  .subscribe(val => this.getAgentsInShiftAndDispo());
            
        ,
    (err) => console.error(err));


getAgentsInShiftAndDispo() 
    this.agentsInShift = [];
    this.agents_dispo = [];
    this.agentsInShiftSelectedFormArray.clear();
    this.agentsDispoFormArray.clear();
    if (this.selectedShiftForMaincouranteModify !== 0 &&
        (this.modifyForm.controls.dateDeb.value !== "" || this.modifyForm.controls.dateDeb.value !== null || this.modifyForm.controls.dateDeb.value !== undefined)) 
        const shift_id = this.selectedShiftForMaincouranteModify;
        const goodFormatDate = this.modifyForm.value.dateDeb.format('YYYY-MM-DD');
        this.api.sendGetRequest('/api/shift_dos/byShiftAndDate/' + shift_id + "/" + goodFormatDate, true, null, null)
            .subscribe((data) => 
                if (data) 
                    data.forEach((item) => 
                        this.agentsInShift.push(item.agent);
                    );
                
            , (err) => console.error(err),
            () => 
                this.agentsInShift.map((o, i) => 
                    const control = new FormControl(true); // if first item set to true, else false
                    this.agentsInShiftSelectedFormArray.push(control);
                );
                const difference = this.agentsMaintenance.filter((obj) => 
                    return !this.agentsInShift.some((obj2) => 
                        return obj.id === obj2.id;
                    );
                );
                this.agents_dispo = difference;
                this.agents_dispo.map((o, i) => 
                    const control = new FormControl(false); // if first item set to true, else false
                    this.agentsDispoFormArray.push(control);
                );
            );
    

【讨论】:

谢谢你,我正在寻找:D 很高兴为您提供帮助!如果它按预期工作,请不要忘记请接受答案。这也将帮助其他用户。谢谢!

以上是关于在 foreach 中等待几个可观察的 rxjs 直到完成执行另一个的主要内容,如果未能解决你的问题,请参考以下文章

Rxjs 可观察等待,直到满足某些条件

不推荐使用 Rxjs toPromise()

如何让观察者在认证后等待 WebSocket 的创建

在 Angular 6 中使用 rxjs 可观察对象的目的是啥?与 async/await 相比,rxjs 的优势是啥? [复制]

Rxjs 可观察到承诺永远不会在 nodejs 中解决

rxjs中常用的操作符