我们说你有:
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 ,以便在之后的 块之后执行 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调用之后自动执行foo 代码之后。我知道我可以使用回调来实现这一点,但我真的很想坚持使用promises。
答案 0 :(得分:3)
好吧,让我们看看你在这里问的是什么:
有没有办法修改foo,以便在After foo 块之后执行afterItAll?
这实际上是在问:
有没有办法知道什么时候不再有
.then
个处理程序添加到特定的承诺中?
在给定任意函数的情况下,我们可以决定在fooResult.then(function(){})
之前添加return
作为程序中的最后一项,所以它就像问:
有没有办法知道函数何时返回?
在整个程序作为一个函数的情况下,就像问:
有没有办法知道程序是否会停止?
It's not an easy thing to do至少可以说。这个特征不仅不存在,理论上也是不可能的。
Bergi's answer为您提供了一个非常好的主意。我们在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
然后运行另一个并且将记录"之后全部"两个完成后。此模式对于DB驱动程序和资源获取非常有用。
答案 1 :(得分:1)
不,没有这样的承诺构造。承诺不会 - 不能 - 知道它是否是链的末尾,或者某些其他代码是否会附加另一个链接。
组合promises和回调代码没有错:
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's Promise.using
资源管理模式。
答案 2 :(得分:0)
OK!我希望我的经验对你有帮助。
我有类似的问题。
我希望在执行所有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模块