繁体   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