是否可以覆盖已经声明的Promise链?

时间:2017-09-16 20:41:16

标签: javascript html promise

我有一个异步行为的保存功能,因此我使用的是promises。主要保存事件将进入并且只有一次{...}}和then处理程序附加到它们。对于我的代码示例,这将在catch方法中发生。现在可能会有以后调用的任意数量的其他保存调用,您可以参考importantSave方法。

有没有办法让sideSave方法中的thencatch处理程序在调用之前等待所有的侧面保存解析/拒绝,即使它们是先建立?

例如,我有以下代码:

importantSave

有没有办法改变这一点,以便在sideSave调用中任何class Adapter { promise; next_attempt; attempt() { if ( this.promise && this.promise.isPending() ) { this.next_attempt = this.attempt.bind( this ); return this.promise.then( ()=> { if ( this.next_attempt ) { return this.next_attempt(); } } ); } else { this.promise = new Promise( resolve=> { setTimeout( resolve, 3000 ); } ); return this.promise; } } } const adapter = new Adapter(); function importantSave() { adapter.attempt() .then( ()=> { console.log( 'Hello from the important save!' ); } ); } function sideSave() { adapter.attempt() .then( ()=> { console.log( 'Hello from the side save!' ); } ); } // the important save which sets up its then and catches, but wants to be called after all have finished importantSave(); // any number of side saves, but will only be called with the last side save sideSave(); sideSave(); sideSave(); 之后实际运行importantSave中的then?我的真实世界示例将在每次调用之间延迟调用保存功能3次,并且只有在所有3次失败时才会拒绝。如果在所有3次失败之前发生另一次保存调用,我希望最新的调用是“next_attempt”,覆盖任何其他尝试保存,而第一次仍未决。如果原始调用未能保存,但是其中一个“sideSave”调用已通过,我希望thens完成,从而落入当时,而不是原始调用失败的捕获。

1 个答案:

答案 0 :(得分:1)

通常这样做的方式是使用Promise.all

添加您需要在数组中解析的所有promise并将其作为参数传递:

Promise.all([importantSave(), sideSave(), sideSave(), sideSave()]).then(_ => {
    console.log('all done');
});

您当然可以动态构建数组:

var arr = [importantSave()];

arr.push(sideSave());
arr.push(sideSave());
arr.push(sideSave());

Promise.all(arr).then(_ => {
    console.log('all done');
});

如果你只需要一个人来实现,那就使用与这些承诺相反的方法。您可以使用辅助函数:

const invert = p => p.then(resp => { throw resp }).catch(err => err);

此函数返回一个承诺,该承诺将在其参数满足时拒绝,反之亦然。

现在你可以做到:

var arr = [importantSave()];

arr.push(sideSave());
arr.push(sideSave());
arr.push(sideSave());

invert(Promise.all(arr.map(invert))).then(_ => {
    console.log('one done');
});