Angular 2为什么我的4个api调用在执行前等待上一个调用完成?

时间:2017-09-08 13:34:55

标签: angular typescript angular-promise typescript2.0 angular-observable

我有form / component,必须执行4次单独的API调用才能执行" save"。实际上,这些交易中只有一个需要等待其他3个交易,但为了安全起见,我想将所有4个交易链接起来。

以下是我如何设置:

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 dev工具查看我的控制台窗口,并看到来自API调用的响应开始进入。

为什么此设置不接受这些事务的显式链接?我知道在Angular 1中,使用promise并执行.then(response => {});非常容易。

我能想到的唯一不同之处就是每次API调用,无论是get / post / put / delete ,它总是在chrome dev工具的网络面板中显示2个调用。第一个调用将RequestMethod设置为Options,而后续调用则是相应的get / post / put / delete RequestMethod相应地设置。

我不记得曾经在我最近的任何应用程序中看过那些(重复的电话),(也许我从来没有注意过那么多)所以也许这只是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({});行上给我一个错误说:

  

类型的参数&#39;(错误:任何)=&gt; 0 | 1&#39;不能转让给   参数类型&#39;(错误:任何,捕获:可观察&lt; 0 | 1&gt;)=&gt;   ObservableInput&LT; {}&GT;&#39 ;.输入&#39; 0 | 1&#39;不能分配给类型   &#39;&ObservableInput LT; {}&GT;&#39 ;.       输入&#39; 0&#39;不能分配给&#39; ObservableInput&lt; {}&gt;&#39;。)

2 个答案:

答案 0 :(得分:1)

您的代码可能有很多问题。首先,save1 / save2 / save3方法应该只返回您可以订阅的API中的observable。

其次,您使用的是 int 类型,这在Typescript中是不存在的。使用数字

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)
}

如果您想修改发出的项目,可以添加地图操作符,将发出的项目映射到其他项目。

最后,你应该避免在一个可观察者中订阅一个观察者。您可以使用 flatMap 运算符将可观察对象链接在一起。这会将Observable发出的项目转换为Observables,然后将这些项目的排放量变为单个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

答案 1 :(得分:0)

我认为你需要“回归”你的观察者。例如:

改变这个:

this.api.save1(saveObject)

要:

return this.api.save1(saveObject)