[英]How to execute code at the very end of a promise chain in q
假設您有:
function setTimeoutPromise(ms) {
var defer = Q.defer();
setTimeout(defer.resolve, ms);
return defer.promise;
}
然后您會看到類似:
function foo(ms) {
return setTimeoutPromise(ms).then(function () {
console.log('foo');
});
}
function afterItAll() {
console.log('after it all');
}
foo(100).then(function () {
console.log('after foo');
}).then(afterItAll);
有沒有一種方法可以修改foo,以便在after foo塊之后執行afterItAll ? 例如:
function foo(ms) {
return setTimeoutPromise(ms).then(function () {
console.log('foo');
}).SOMEPROMISECONSTRUCT(function () {
console.log('after it all');
});
}
foo(100).then(function () {
console.log('after foo');
});
我問的原因是我正在開發一個API,用戶將在其中進行幾個此類foo調用,並且如果在這些API調用之后自動執行after foo代碼,它將大大減少用戶的代碼。 我知道我可以使用回調來完成此操作,但是我真的很想堅持使用諾言。
好吧,讓我們在這里看到您的要求:
有沒有一種方法可以修改foo,以便在after foo塊之后執行afterItAll?
這實際上是在問:
有什么方法可以知道何時不再將
.then
處理程序添加到特定的Promise嗎?
其中,給定任意函數我們可以決定添加fooResult.then(function(){})
如在程序中的最后一件事之前,我們return
的,因此它就像問:
有什么方法可以知道何時/是否會返回一個函數嗎?
給定整個程序的功能,就像問:
有沒有辦法知道程序是否會停止?
至少要說這不是一件容易的事 。 不僅不存在此功能,而且從理論上講也是不可能的。
Bergi的答案為您提供了一個不錯的主意。 我們在Bluebird中爭取的核心是嵌套。
因為我們想要在一般情況下是不可能的事情,所以我們必須像回調一樣反轉控制:
function transaction(fn){
// Promise.resolve().then( in ES6/Bluebird promises
return Q().then(function(){
return fn()
}).finally(function(){ // same in Bluebird, in ES6 that's `.then(fn, fn)`
console.log("after it all!");
})
}
這可以讓您做到:
transaction(function(){
return setTimeoutPromise().then(more).then(more);
});
哪個將運行setTimeoutPromise,然后運行more
,然后運行另一個,並且在兩個都完成之后將“全部記錄”。 此模式對於數據庫驅動程序和資源獲取非常有用。
不,沒有這樣的諾言構造。 一個諾言不能-不能-知道它是一條鏈的末端,還是其他代碼是否將另一個鏈接附加到它。
但是,將promise和回調代碼組合在一起並沒有錯:
function foo(ms, within) {
return setTimeoutPromise(ms).then(function () {
console.log('foo');
})
.then(within)
.then(function afterFooAll() { // possibly use `finally` here?
console.log('cleanup');
});
}
foo(100, function () {
console.log('inside foo');
}) // now returns a promise for cleanup been done
我不確定您的實際用例是什么,但是您可能還想看看Bluebird的Promise.using
資源管理模式。
好! 希望我的經驗對您有所幫助。
我有非常類似的問題。
我希望在執行所有sql語句后釋放mysql連接池,否則會失敗...如下所示
getConnection
.then(exeuteSQL('select ...'))
.then(exeuteSQL('select ...'))
.then(null, function(err){ //err handling })
....
.. finally execute pool release
這樣可以完成.done()方法
getConnection
.then(exeuteSQL('select ...'))
.then(exeuteSQL('select ...'))
.then(null, function(err){ //err handling })
....
.done(function(){
console.log('this line always executed!');
req.conn.release(); // assuming connection attached to request object before
})
PS)我的應用程序環境是node.js並使用'q'promise模塊
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.