我正在使用Q节点库进行Promises,我认为这个问题也适用于Bluebird lib。
我有几个函数调用来调用我自己的自定义函数和node.js fs
样式的异步函数。
如果我正在调用这样的函数:
同步功能
do_something = function (input) {
// assign variables, do other sync stuff
}
并且需要以上功能before
此功能:
同步功能
do_something_else = function (input) {
// assign variable, do other sync stuff
}
和then
需要调用类似于:
异步功能
writeData = function (obj, callback) {
var deferred = Q.defer();
fs.writeFile(obj.file, obj.datas, function (err, result) {
if (err) deferred.reject(err);
else deferred.resolve('write data completed');
});
return deferred.promise.nodeify(callback);
}
和finally
需要执行上述before
此功能:
同步功能
do_something_last = function (input) {
// assign variable, do other sync stuff
}
'正确'在这里做的事情,使我的所有功能延迟'或承诺知道所以我可以确保按顺序或以正确的顺序调用它们? 像这样:
do_something(variable)
.then(do_something_else)
.then(writeData)
.then(do_something_last)
.done();
或者我应该这样做而不是保持排序(排序)?像这样:
var variable1 = 'test1.txt'
var variable2 = 'test2.txt'
var return_value = do_something(variable1);
var return_another_value = do_something_else(return_value); <--sync
writeData(return_another_value); <-- async function
var final_value = do_something_last(variable2); <-- sync function
// could potentially have async calls again after a sync call
writeDataAgain(return_another_value); <-- async function
我的想法是因为其中一些同步函数需要在异步后触发,我需要让它们知道Promise以保持序列顺畅,如下所示:
同步功能使得承诺意识到
do_something = function (input) {
var deferred = Q.defer();
// assign variables, do other sync stuff
deferred.resolve(_output_result_);
return deferred.promise;
}
do_something_else = function (input) {
var deferred = Q.defer();
// assign variables, do other sync stuff
deferred.resolve(_output_result_);
return deferred.promise;
}
do_something_last = function (input) {
var deferred = Q.defer();
// assign variables, do other sync stuff
deferred.resolve('completed workflow');
return deferred.promise;
}
这将允许我这样做:
do_something(variable)
.then(do_something_else) <-- these need to execute before writeData
.then(writeData) <-- a async node fs call to writeFile
.then(do_something_last) <-- I need this to happen after the writeDate
.done();
在我阅读完反馈后,我想我真正想要的是:
如何创建功能工作流程,混合非承诺同步和 承诺感知的异步函数调用,同时保持排序 执行(或排序)?
答案 0 :(得分:3)
只需执行此操作并按顺序保留顺序:
writeData(return_another_value); var final_value = do_something_last(variable2);
嗯,这简直无法工作,因为do_something_last
承诺已解决后未调用writeData(…)
。它只是在创建并返回promise后立即启动。因此,如果您关心该特定订单并希望等到数据写入,那么您需要使用then
进行回调:
var final_promise = writeData(return_another_value).then(function(writeResult) {
return do_something_last(variable2);
});
一般规则是:
您可以将同步函数放在then
链中,非承诺返回值(甚至抛出的异常)可以正常工作。
所以,当你可以编写你的序列时,如
Q('test1.txt')
.then(do_something)
.then(do_something_else)
.then(writeData)
.then(do_something_last.bind(null, 'test2.txt'))
.done();
它看起来很奇怪。如果您因某些原因不打算在不久的将来使do_something
异步,那么编写和读取通常会更简单
writeData(do_something_else(do_something('test1.txt'))).then(function() {
return do_something_last('test2.txt');
}).done();
不可否认,写作
有时更具吸引力somePromise()
.then(doSomethingSynchronous)
.then(doSomethingAsynchronous)
大于
somePromise
.then(function(res) { return doSomethingAsynchronous(doSomethingSynchronous(res)); })
即使它们功能相同。选择你喜欢的风格更好,更一致。
答案 1 :(得分:1)
如果您关心的是您的功能是否按顺序进行,请执行以下操作:
do_something(variable)
.then(do_something_else)
.then(writeData)
.then(do_something_last)
.done();
当您要传递这些变量(例如传递给其他服务)或使用它们创建不同的承诺链时,您只会将变量分配给变量。
e.g
var promise = do_something('123')
// two different promise chains
var task1 = promise.then(function(res){
// logic
})
var task2 = promise.then(function(res){
// other logic, independent from task1
})