Angular 2 为什么我的 4 api 调用没有等待前一个调用完成后再执行?
Angular 2 why aren't my 4 api calls waiting for the previous call to finish before executing?
我有一个 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 开发工具中查看我的控制台 window,并查看来自API 来电开始。
为什么此设置不接受这些事务的显式链接?我知道在 Angular
1 中,使用 promise
和 .then(response => {});
.
很容易做到这一点
我能想到的唯一不同之处在于每个 API 调用,无论是 get
/post
/put
/delete
,它总是在 chrome 开发工具的网络面板中显示 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({});
行上向我抛出一个错误:
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<{}>'.)
我认为您需要 "return" 您的可观察对象。例如:
改变这个:
this.api.save1(saveObject)
收件人:
return this.api.save1(saveObject)
您的代码存在很多问题,这些问题可能与此有关。首先,您的 save1/save2/save3 方法应该只是 return 您可以订阅的 API 的可观察对象。
其次,您使用的是 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)
}
如果您想修改发射的项目,您可以添加映射运算符,将发射的项目映射到其他东西。
最后,你应该避免从一个可观察对象中订阅一个可观察对象。您可以使用 flatMap 运算符将可观察对象链接在一起。这会将 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
});
}
我有一个 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 开发工具中查看我的控制台 window,并查看来自API 来电开始。
为什么此设置不接受这些事务的显式链接?我知道在 Angular
1 中,使用 promise
和 .then(response => {});
.
我能想到的唯一不同之处在于每个 API 调用,无论是 get
/post
/put
/delete
,它总是在 chrome 开发工具的网络面板中显示 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({});
行上向我抛出一个错误:
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<{}>'.)
我认为您需要 "return" 您的可观察对象。例如:
改变这个:
this.api.save1(saveObject)
收件人:
return this.api.save1(saveObject)
您的代码存在很多问题,这些问题可能与此有关。首先,您的 save1/save2/save3 方法应该只是 return 您可以订阅的 API 的可观察对象。
其次,您使用的是 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)
}
如果您想修改发射的项目,您可以添加映射运算符,将发射的项目映射到其他东西。
最后,你应该避免从一个可观察对象中订阅一个可观察对象。您可以使用 flatMap 运算符将可观察对象链接在一起。这会将 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
});
}