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