Angular 2为什么我的4 api调用不会等待之前的调用在执行前完成?

问题描述:

我有一个form/component必须做4个独立的API调用才能执行“保存”。真的,这些交易中只有一个需要等待其他3个交易,但我想要将所有4个交易链接起来以保证安全。Angular 2为什么我的4 api调用不会等待之前的调用在执行前完成?

以下是我把它设置:

save() { 
    this.save1(saveObject1) 
     .subscribe(response => { 
      if (response === 0) { 
       this.processErrorResult('save1'); 
      } 

      this.save2(saveObject2) 
       .subscribe(response2 => { 
        if (response2 === 0) { 
         this.processErrorResult('save1'); 
        } 

        this.save3(saveObject3) 
         .subscribe(response3 => { 
          if (response3 === 0) { 
           this.processErrorResult('save1'); 
          } 

          if (this.noErrorsInFirst3Saves()) { 
           this.save4(saveObject4) 
            .subscribe(response4 => { 
             if (response4 === 0) { 
              this.processErrorResult('save1'); 
             } 

             if (!this.hasErrors()) { 
              this.router.navigate(['confirmation']); 
             } 
            }); 
          } 
         }); 
       }); 
     }); 
} 

private save1(saveObject: any): Observable<int> { 
    this.api.save1(saveObject) 
     .subscribe(successful => { 
      return Observable.of(1); 
     }, failed => { 
      return Observable.of(0); 
     }); 
} 

private save2(saveObject: any): Observable<int> { 
    this.api.save2(saveObject) 
     .subscribe(successful => { 
      return Observable.of(1); 
     }, failed => { 
      return Observable.of(0); 
     }); 
} 

private save3(saveObject: any): Observable<int> { 
    this.api.save3(saveObject) 
     .subscribe(successful => { 
      return Observable.of(1); 
     }, failed => { 
      return Observable.of(0); 
     }); 
} 

private save4(saveObject: any): Observable<int> { 
    this.api.save4(saveObject) 
     .subscribe(successful => { 
      return Observable.of(1); 
     }, failed => { 
      return Observable.of(0); 
     }); 
} 

每个里面那些save{number}功能我有日志消息,所以我清楚地知道,这些功能得到执行(和响应回来)的顺序。

当我点击保存,它[几乎]立即重定向到我的确认页面,然后我就可以坐在那里,看着在Chrome浏览器开发工具,我的控制台窗口,看到来电开始进来的API响应。

为什么这个设置不接受这些事务的显式链接?我知道在Angular 1中,用promise做这个很容易,并且做了.then(response => {});

,我能想到的,是唯一不同的,是每个API调用,不管它是一个get/post/put/delete,它总是显示在Chrome浏览器开发工具,网络面板2所调用。第一个呼叫的RequestMethod设置为Options,而随后的呼叫是相应设置的RequestMethod,对应的get/post/put/delete

我不记得曾经在我最近的任何应用程序中看到这些(重复调用),(也许我只是从未注意过太多),所以也许这只是API的标准操作过程调用。

这里的任何想法?

编辑:针对哈利的建议答复如下

我想实现你的答案,但还是有点困惑就如何实施,这里是我的设置仔细一看:

private save1(saveObject: any): Observable<number> { 
    if (saveObject.hasChanges()) { 
     return this.api.save1(saveObject) 
      .map(successful => { 
       return this.parseSaveResponse(successful, saveObject, true); // true indicates a successful API response 
      }) 
      .catch(failed => { 
       return this.parseSaveResponse(successful, saveObject, false); // false indicates a successful API response 
      }); 
    } else { 
     return Observable.of(-1); // no changes necessary, return immediately 
    } 
} 

private parseSaveResponse(response: any, saveObject: any, transactionSuccessful: boolean) { 
    this.logService.logTransaction({transactionType}, saveObject, response, transactionSuccessful); 

    if (!transactionSuccessful) { 
     // add to error list object to be displayed on the form 
     return 0; 
    } 

    return 1; 
} 

当得到这一点,它抛出我的错误就行.catch({});说:

Argument of type '(error: any) => 0 | 1' is not assignable to parameter of type '(err: any, caught: Observable<0 | 1>) => ObservableInput<{}>'. Type '0 | 1' is not assignable to type 'ObservableInput<{}>'. Type '0' is not assignable to type 'ObservableInput<{}>'.)

+0

的面貌迈向switchmap算符变换rxjs到链您的来电。它可以将Observable作为输入,并且可以使用它来调用其他API。如果您想等待,您可以查看Observable.forkJoin方法 – DOMZE

的Theres相当多的问题。首先,您的save1/save2/save3方法应该只返回您可以订阅的API中的observable。

其次,您正在使用TypeScript中不存在的int类型。使用号码

private save1(saveObject: any): Observable<number> { 
    return this.api.save1(saveObject); 
} 
// or 
private save1(saveObject: any): Observable<number> { 
    return this.api.save1(saveObject).map(response => 1).catch(response => 0) 
} 

如果你想修改发射,你可以添加地图操作它映射发射到别的项目的项目。

最后,您应该避免从observable内部订阅observable。您可以使用运算符将​​observables链接在一起。这将Observable发射的物品转换为Observable,然后将这些物品的排放物变成单个Observable。

save() { 
    this.save1(saveObject1) 
    .flatMap(response1 => this.save2(saveObject2)) 
    .flatMap(response2 => { 
     if (response2 === 0) { 
     // handle error 
     } 
     return this.save3(saveObject3); 
    }) 
    .flatMap(() => this.save4(saveObject4)) 
    .subscribe(response4 => { 
     // do redirect 
    }); 
    } 

http://reactivex.io/documentation/operators/flatmap.html

+0

对不起,他们已经返回Observable ,那只是一个伪代码写作,忘记了我在打字稿世界而不是C#。通过其余的你的回应... – ganders

+0

请看我上面的编辑... – ganders

+0

我相信我已经得到它的工作....一旦我确认一些更多的测试,我会更新我的问题有工作版本,我会给你你的答案。谢谢[我认为] ... – ganders

我认为你需要“返回”你的观察对象。例如:

更改此:

this.api.save1(saveObject) 

要:与您的代码可能是导致

return this.api.save1(saveObject) 
+0

,即使这些'this.api.save1()'调用都有一个'.subscribe',并且它们正在执行'return Observable.of({number });'? – ganders

+0

@ganders是的。你需要返回 – vidalsasoon

+0

一旦我添加返回你说的,vscode抛出整个块下的红色错误行说:'类型订阅不可分配到类型Observable ' – ganders