我试图做一些有点棘手的事情,因为我还不习惯承诺。
我想填写<Id, ObjectInfo>
我有两个API点:
这就是我所拥有的:
const result: Map<string, String[]> = new Map();
return this.http.get(this.adress + '/', this.options).toPromise()
.then((response) => {
for (const id of response.json()){
this.http.get(this.adress + '/' + id + '/properties').toPromise()
.then((rep) => {
result.set(id, rep.json());
console.log('#1: ', result);
}).catch(this.handleError)
}
})
.then(() => console.log('#2: ', result))
.then(() => result)
.catch(this.handleError);
所以在这里,我希望#1在控制台中跟随#2,但事实并非如此。我知道我应该尝试Promise.all()
,但我真的不知道如何设置它,因为我在嵌套循环中创建了Promise。
这是一个Angular项目,实际代码到目前为止工作,但抛出 ExpressionChangedAfterItHasBeenCheckedError 。
为了避免这种情况,改变我的诺言功能应该可以解决问题。
答案 0 :(得分:4)
这部分代码
.then((response) => {
// <-- HERE -->
// this function must return a promise
for (const id of response.json()){
// ...
}
})
.then(() => {
// right now, this function executes **before** the requests
// in the promise above are resolved
});
必须返回一个解析其中所有单个promise(在循环中构建的promise)的promise,因此promise链可以拥有你想要的顺序 - 在循环之前等待循环中的所有promise。
在这里使用Promise.all
是很自然的,只需用数组映射替换for..of
:
.then((response) => {
return Promise.all(
Array
.from(response.json())
.map(id => {
return this.http.get(this.adress + '/' + id + '/properties')
.toPromise()
.then((rep) => {
result.set(id, rep.json());
console.log('#1: ', result);
})
.catch(this.handleError)
})
);
})
.then(...)