簡體   English   中英

如何在q中的承諾鏈的最后執行代碼

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM