我想運行相同的操作,無論我的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承諾
- 3. 承諾在JavaScript(ES6)
- 4. ES6嵌套承諾
- 5. 承諾es6和superagent
- 6. ES6異步承諾
- 7. 混合firebase承諾與ES6承諾
- 8. ES6承諾 - 在承諾鏈中調用同步功能
- 9. 鏈接.then()調用ES6承諾
- 10. ES6承諾錯誤處理
- 11. 使用Sequelize和ES6承諾?
- 12. ES6解構的承諾?
- 13. 從when.js移到ES6承諾
- 14. ES6承諾執行訂單
- 15. ES6承諾 - 類似async.each?
- 16. 回覆承諾的承諾
- 17. 回調還是承諾?
- 18. AngularJS承諾沒有回調?
- 19. 藍鳥承諾和回調
- 20. NodeJS:承諾內的回調
- 21. 從承諾中回報價值:回調或承諾?
- 22. 混合使用J6承諾的ES6承諾
- 23. 由於ES6承諾的替代承諾未定義
- 24. ES6承諾/打字稿和藍鳥承諾
- 25. 藍鳥承諾作爲承諾回調不知道api
- 26. TypeScript覆蓋ES6承諾與藍鳥
- 27. 我只是沒有得到ES6「承諾」
- 28. Es6訪存/承諾上下文
- 29. 創建尚未解決的承諾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