何时使用Promises延迟函数

时间:2015-03-11 17:42:10

标签: javascript angularjs node.js asynchronous promise

我正在使用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();

在我阅读完反馈后,我想我真正想要的是:

  

如何创建功能工作流程,混合非承诺同步和   承诺感知的异步函数调用,同时保持排序   执行(或排序)?

2 个答案:

答案 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);
});

一般规则是:

  • 使同步功能同步 - 不需要承诺
  • 使所有异步函数始终返回一个承诺
  • 仅在promisification
  • 的最低级别使用延迟

您可以将同步函数放在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
})