何时使用 Promises 延迟函数
When to make a function deferred using Promises
我正在为 Promises 使用 Q 节点库,我认为这个问题也适用于 Bluebird 库。
上下文
我有几个函数调用要对我自己的自定义函数和 node.js fs
风格的异步函数进行调用。
如果我正在调用这样的函数:
sync function
do_something = function (input) {
// assign variables, do other sync stuff
}
并需要上述功能发生 before
这个功能:
sync function
do_something_else = function (input) {
// assign variable, do other sync stuff
}
和then
需要调用类似于以下的原生节点函数:
async function
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
这个函数:
sync function
do_something_last = function (input) {
// assign variable, do other sync stuff
}
问题
这里要做的 'right' 事情是为了让我的所有函数 'deferred' 或 promise 知道,以便我可以确保它们按顺序或以正确的顺序调用?
像这样:
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 以保持顺序正确,就像这样:
sync functions made promise aware
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();
在我阅读了反馈后,我想我真正想问的是:
How do I create a function workflow, mixing non-promise sync and
promise-aware async function calls, all the while keeping the ordering
(or sequencing) of execution?
如果你只关心你的函数是否按顺序执行,那么这样做:
do_something(variable)
.then(do_something_else)
.then(writeData)
.then(do_something_last)
.done();
只有当您要传递这些变量(例如,传递给其他服务)或使用它们创建不同的承诺链时,您才将承诺分配给变量。
例如
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
})
just do this instead and keep the ordering like so:
writeData(return_another_value);
var final_value = do_something_last(variable2);
好吧,那根本行不通,因为 do_something_last
在 writeData(…)
承诺 已解决 之后不会被调用。它会在 promise 创建并 returned 后立即开始。因此,如果您关心该特定订单并想等到数据写入,那么您 需要 将 then
与回调一起使用:
var final_promise = writeData(return_another_value).then(function(writeResult) {
return do_something_last(variable2);
});
一般规则是:
- 使同步函数同步 - 不需要承诺
- 使所有异步函数始终return成为承诺
- 仅在 promisification
的最低可能级别使用延迟
您可以将 同步函数放在 then
链 中,非承诺 return 值(甚至抛出的异常)在其中工作正常。
所以当你可以写你的序列时
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)); })
即使它们功能相同。选择自己比较喜欢的风格,也比较连贯。
我正在为 Promises 使用 Q 节点库,我认为这个问题也适用于 Bluebird 库。
上下文
我有几个函数调用要对我自己的自定义函数和 node.js fs
风格的异步函数进行调用。
如果我正在调用这样的函数:
sync function
do_something = function (input) {
// assign variables, do other sync stuff
}
并需要上述功能发生 before
这个功能:
sync function
do_something_else = function (input) {
// assign variable, do other sync stuff
}
和then
需要调用类似于以下的原生节点函数:
async function
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
这个函数:
sync function
do_something_last = function (input) {
// assign variable, do other sync stuff
}
问题
这里要做的 'right' 事情是为了让我的所有函数 'deferred' 或 promise 知道,以便我可以确保它们按顺序或以正确的顺序调用? 像这样:
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 以保持顺序正确,就像这样:
sync functions made promise aware
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();
在我阅读了反馈后,我想我真正想问的是:
How do I create a function workflow, mixing non-promise sync and promise-aware async function calls, all the while keeping the ordering (or sequencing) of execution?
如果你只关心你的函数是否按顺序执行,那么这样做:
do_something(variable)
.then(do_something_else)
.then(writeData)
.then(do_something_last)
.done();
只有当您要传递这些变量(例如,传递给其他服务)或使用它们创建不同的承诺链时,您才将承诺分配给变量。
例如
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
})
just do this instead and keep the ordering like so:
writeData(return_another_value); var final_value = do_something_last(variable2);
好吧,那根本行不通,因为 do_something_last
在 writeData(…)
承诺 已解决 之后不会被调用。它会在 promise 创建并 returned 后立即开始。因此,如果您关心该特定订单并想等到数据写入,那么您 需要 将 then
与回调一起使用:
var final_promise = writeData(return_another_value).then(function(writeResult) {
return do_something_last(variable2);
});
一般规则是:
- 使同步函数同步 - 不需要承诺
- 使所有异步函数始终return成为承诺
- 仅在 promisification 的最低可能级别使用延迟
您可以将 同步函数放在 then
链 中,非承诺 return 值(甚至抛出的异常)在其中工作正常。
所以当你可以写你的序列时
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)); })
即使它们功能相同。选择自己比较喜欢的风格,也比较连贯。