我已经创建了一个数组来存储应许列表,该应许列表应在一次调用Promise.all之后运行,但是在将这个新的Promise推入数组后立即执行。我该如何解决?
let promises: any[] = [];
this.tasklistItems.forEach(element => {
if (element.checked) {
promises.push(new Promise(() => this.tasklistItemsService.delete(this.tasklist, element.id))); // It gets executed right after this line
}
});
Promise.all(promises) // But I need to start executing here
.then((res) => { // So I can get all responses at the same place, together
this.notification.success('Success!', 'Rows removed.');
},
(err) => {
});
按照@Evert的建议,现在我有以下代码:
const deferred = [];
this.tasklistItems.forEach(element => {
if (element.checked) {
deferred.push(() => this.tasklistItemsService.delete(this.tasklist, element.id).subscribe());
}
});
Promise.all(deferred.map(func => func()))
.then(
() => {
this.notification.success('Sucess!', 'Rows removed.');
this.refreshGrid();
},
err => {
console.log(err);
this.notification.error('Error!', 'Could not remove the selected rows.');
}
);
这是我使用HttpClient
的服务:
delete(tasklistId: number, id: number): Observable<boolean> {
return this.http.delete(`${this.baseUrl}/${tasklistId}/items/${id}`)
.pipe(catchError(this.handleError));
}
如果我没有将subscribe()
添加到delete(...)
调用中,则不会执行它,如果添加它,则在删除发生之前将调用refreshGrid()
。
答案 0 :(得分:2)
此行中断:
new Promise(() => this.tasklistItemsService.delete(this.tasklist, element.id)
除此之外,承诺通常会立即执行。它们不是将执行推迟到以后的机制。值得庆幸的是,javascript对此非常简单:一个简单的旧函数。
const deferred = [];
this.tasklistItems.forEach(element => {
if (element.checked) {
deferred.push(() => this.tasklistItemsService.delete(this.tasklist, element.id)));
}
}
// Iterates over all stored functions, calls them all and returns the result as an array of promises.
Promise.all( deferred.map( func => func() ) );
答案 1 :(得分:0)
通常,.forEach()
和Promise.all()
不能很好地融合在一起,创建延迟承诺的数组会增加一些不必要的步骤。 (诺兰·劳森的"We have a problem with promises"在解决这两个问题上做得很好。)正如@Evert所提到的,这是因为诺言是“渴望的”,并在它们被构造后立即执行。
您似乎想获取一个数组,筛选出未选中的选项,然后从中解决一个promise数组。直接在.filter()
中使用.map()
和Promise.all()
怎么样?
Promise.all(
this.tasklistItems
.filter(element => element.checked)
.map(checkedElement => this.tasklistItemsService.delete(this.tasklist, checkedElement.id)
)
.then((res) => { // So I can get all responses at the same place, together
this.notification.success('Success!', 'Rows removed.');
},
(err) => {});