我想运行相同的操作,无论我的Promise是否成功解决。我不想将相同的函数绑定到.then
的两个参数。是不是像jQuery一样有.always
?如果不是,我该如何实现?ES6承诺结算回调?
回答
是不是有像jQuery一样的
.always
?
不,there's not (yet)。虽然有一个active proposal,所以也许ES2018。
如果不是,我该如何做到这一点?更广泛地
Promise.prototype.finally = function(cb) { const res =() => this const fin =() => Promise.resolve(cb()).then(res) return this.then(fin, fin); };
,或者与传递分辨率信息回调:
您可以实现finally
方法自己这样
Promise.prototype.finally = function(cb) {
const res =() => this
return this.then(value =>
Promise.resolve(cb({state:"fulfilled", value})).then(res)
, reason =>
Promise.resolve(cb({state:"rejected", reason})).then(res)
);
};
两个确保原始分辨率是持续(当回调中没有异常时)并且正在等待承诺。
随着异步/ AWAIT,你可以的await
与try/finally
组合,像这样:
async function(somePromise) {
try {
await somePromise();
} finally {
// always run this-- even if `somePromise` threw something
}
}
以下是我已经在生产中使用的节点上运行,用巴贝尔的async-to-generator插件一个真实的例子。
// Wrap promisified function in a transaction block
export function transaction(func) {
return db.sequelize.transaction().then(async t => {
Sequelize.cls.set('transaction', t);
try {
await func();
} finally {
await t.rollback();
}
});
}
我使用此代码摩卡测试旁边的Sequelize ORM内启动一个数据库事务,无论DB的结果调用的测试中,始终回滚底。
这大致类似于蓝鸟的.finally()
方法,但IMO,更好的语法!
(注意:。如果你想知道为什么我不await
荷兰国际集团第一个承诺 - 这是Sequelize的实现细节它采用CLS为“捆绑” SQL事务的无极链任何在之内产生,同一个链被限制在事务中,外面的任何东西都不是,所以在Promise上等待会关闭事务块并破坏链,我把这个例子展示给你看,'vanilla '承诺处理可以与异步函数一起混合使用,并且可以很好地协同工作。)
如果您没有/无法更新原型,最终破解方法是:
executeMyPromise()
.then(function(res){ return {res: res}; })
.catch(function(err){ return {err: err}; })
.then(function(data) {
// do finally stuff
if (data.err) {
throw data.err;
}
return data.res;
}).catch(function(err) {
// handle error
});
我不认为这是一样的。请参阅[第3和第4点](https://github.com/tc39/proposal-promise-finally#why-not-thenf-f)。我们可以在不修改原型的情况下使用Bergi的解决方案。你只需要调用它:'finallyFunc.call(thePromise,callback)'。与绑定操作符一起工作良好。 – mpen
@mpen,你是对的。修正后编辑。 – user2426679
这里是我的.finally()的实现。
Promise.prototype.finally = function(cb) {
return this.then(v=>Promise.resolve(cb(v)),
v=>Promise.reject(cb(v)));
};
我测试了它:
(new Promise((resolve,reject)=>{resolve(5);})).finally(x=>console.log(x)); //5
(new Promise((resolve,reject)=>{reject(6);})).finally(x=>console.log(x)); //6
(new Promise((resolve,reject)=>{reject(7);}))
.then(x=>x,y=>y)
.catch(x=>{throw "error";})
.finally(x=>{console.log(x); throw "error"; return x;}) // 7
.then(x=>console.log(x),y=>console.log('e')); //e
// Uncaught (in promise) undefined
没有必要引入新的概念
const promise = new Promise((resolve, reject) => {
/*some code here*/
});
promise.then(() => {
/* execute success code */
},() => {
/* execute failure code here */
}).then(() => {},() => {}).then(() => {
/* finally code here */
});
这会导致第一个.then()分支的返回值被丢弃,不是吗? – thenickdude
这是正确的。 –
延长Bergi答案。
在catch处理程序中返回Promise.reject()将防止finnalizing'then'被调用。
所以,如果你要处理的诺言错误2+时候你应该使用的样板是这样的:
return myPromise()
.then(() => ...)
.catch((error) => {
...
myFinnaly();
return Promise.reject(error);
})
.then(() => myFinnaly());
- 1. Javascript承诺链 - ES6
- 2. 承诺es6和superagent
- 3. ES6异步承诺
- 4. ES6嵌套承诺
- 5. 取消ES6承诺
- 6. 承诺在JavaScript(ES6)
- 7. 混合firebase承诺与ES6承诺
- 8. ES6承诺 - 在承诺链中调用同步功能
- 9. 链接.then()调用ES6承诺
- 10. ES6承诺 - 类似async.each?
- 11. ES6承诺执行订单
- 12. 从when.js移到ES6承诺
- 13. ES6承诺错误处理
- 14. ES6解构的承诺?
- 15. 使用Sequelize和ES6承诺?
- 16. 回复承诺的承诺
- 17. 回调还是承诺?
- 18. NodeJS:承诺内的回调
- 19. AngularJS承诺没有回调?
- 20. 蓝鸟承诺和回调
- 21. 从承诺中回报价值:回调或承诺?
- 22. 由于ES6承诺的替代承诺未定义
- 23. 混合使用J6承诺的ES6承诺
- 24. ES6承诺/打字稿和蓝鸟承诺
- 25. 蓝鸟承诺作为承诺回调不知道api
- 26. ES6发电机功能与承诺
- 27. NativeScript Firebase ES6承诺奇怪的行为
- 28. ES6 Dyanmic承诺从数组链
- 29. TypeScript覆盖ES6承诺与蓝鸟
- 30. 使用ES6类时的链接承诺
不能这样做。最后(函数(){...})? –
查看http://stackoverflow.com/questions/26667598/will-javascript-es6-promise-support-done-api –
@CharlieWynn它在Babel中未定义,未列在[MDN](https://developer.mozilla。组织/ EN-US /文档/网络/的JavaScript /参考/ Global_Objects /无极/捕获)。 – mpen