【问题标题】:Angular 6 wait method with subscribe inside内部订阅的Angular 6等待方法
【发布时间】:2020-02-01 17:10:09
【问题描述】:

我必须多次调用一个服务,通过 forEach,一个内部有订阅(http 调用)的方法,我每次都必须等待上一次调用结束。 这是代码:

itemDefaultConfiguration.command = (onclick) => {
   this.createConfiguration(configuration.components);
   //wait the end of createConfiguration method that has subscribe (http call) inside
   this.initializeAllComponents(configuration.components)
};

initializeAllComponents(components: Agent[]) {
    components.forEach(agent => {
      this.componentService.setAgent(agent);
      this.componentService.clearAnyOneOfIndex();
      // wait the end of setAgent method that has subscribe(http call) inside
    })
}

componentService 内部:

setAgent(agent: Agent) {
        this.agent = agent;
        this.selectComponent(agent.name, undefined, "/", "/", environment.maxLevelJsonSchema);
    }

并且 selectComponent 有订阅。

selectComponent(agentName: string, propName: string, schemaPath: string, dataPath: string, deepLevel: number) {
        this.getComponentSchema(this.agentName, schemaPath, deepLevel)
            .subscribe((responseSchema) => {
                this.getDataFailure(propName, dataPath, responseSchema); 
            });
}

你能帮帮我吗?谢谢

【问题讨论】:

  • 你试过什么?您需要付出一些努力,而不是要求我们为您做这件事。乍一看,您可能应该重新考虑该策略。
  • 我尝试了 async/await 但没有改变,我认为 RxJS 有办法
  • @请显示selectComponent方法
  • 与订阅者约会

标签: javascript angular typescript http asynchronous


【解决方案1】:

您可以使用await 来做到这一点,例如:

initializeAllComponents(components: Agent[]) {
    components.forEach(async agent => {
      await this.componentService.setAgent(agent).catch(console.log);
      this.componentService.clearAnyOneOfIndex();
      // wait the end of setAgent method that has subscribe(http call) inside
    })
}

【讨论】:

  • 它不会等待通话结束
  • 表示setAgent之前返回数据!
  • 是的,setAgent 调用另一个有订阅的方法
  • 在setAgent中尝试让setAgent返回订阅本身,这里使用await setAgent().toPromise()
  • forEach 不等待,你需要使用普通的for循环,看我的回答。
【解决方案2】:

您可以使用async/await 语法来实现:

initializeAllComponents(components: Agent[]) {
    for (let i = 0; i < components.length; i++) {
        const agent = components[i];
        await this.componentService.setAgent(agent).catch(console.log);
        this.componentService.clearAnyOneOfIndex();
    }
}

小心async/await,因为您需要使用本机for 循环来等待上一个调用 - forEachreduce 和类似方法只会触发多个异步调用。

【讨论】:

    【解决方案3】:

    如果是Observable,尝试使用switchMap操作符:

    import { switchMap } from 'rxjs/operators';
    import { of } from 'rxjs/observable/of';
    
    initializeAllComponents(components: Agent[]) {
        components.forEach(agent => {
          this.componentService.setAgent(agent).pipe(
               switchMap(res => {
                   if (res) { return this.userService.get(user.uid); }
    
                   return of(null);
               }));
          );
          this.componentService.clearAnyOneOfIndex();          
        })
    }
    

    如果不是Observable,则使用async/await操作符:

    async initializeAllComponents(components: Agent[]) {
        components.forEach(agent => {
          let result = await this.componentService.setAgent(agent);
          this.componentService.clearAnyOneOfIndex();
          // wait the end of setAgent method that has subscribe(http call) inside
        })
    }
    

    【讨论】:

    • 不幸的是它是不可观察的
    • 我更新了第一篇文章,setAgent 调用了另一个方法,里面有订阅
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-24
    • 2019-05-10
    • 1970-01-01
    • 2019-09-05
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    相关资源
    最近更新 更多