javascript - 何时使用 Promises 延迟函数

标签 javascript angularjs node.js asynchronous promise

我正在使用 Q Node 库来实现 Promises,我认为这个问题也适用于 Bluebird 库。

上下文

我需要对我自己的自定义函数和 Node.js fs 风格的异步函数进行一些函数调用。

如果我要调用这样的函数:

sync function

do_something = function (input) {
  // assign variables, do other sync stuff 
}

并且需要在此函数之前执行上述操作:

sync function

do_something_else = function (input) {
  // assign variable, do other sync stuff
}

then需要调用类似于以下内容的 native Node 函数:

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

最后需要在此函数之前进行上述操作:

sync function

do_something_last = function (input) {
  // assign variable, do other sync stuff
}

问题

这里要做的“正确”的事情是让我的所有函数“延迟”或 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?

最佳答案

just do this instead and keep the ordering like so:

writeData(return_another_value);
var final_value = do_something_last(variable2);

好吧,这根本行不通,因为 do_something_lastwriteData(…) promise 解决后不会被调用。解决。它会在 promise 创建并返回后立即开始。因此,如果您关心该特定顺序并希望等到数据写入,那么您需要then与回调一起使用:

var final_promise = writeData(return_another_value).then(function(writeResult) {
    return do_something_last(variable2);
});

一般规则是:

  • 使同步函数同步 - 不需要 Promise
  • 使所有异步函数始终返回 Promise
  • 仅在 promisification 的尽可能最低级别使用延迟

您可以将同步函数放在then链中,非 promise 返回值(甚至抛出异常)在其中可以正常工作。 因此,虽然您可以编写序列,例如

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

即使它们功能相同。选择您更喜欢且更一致的风格。

关于javascript - 何时使用 Promises 延迟函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28993673/

相关文章:

javascript - Jquery 找到没有 id、名称或类的特定 H4

AngularJS 通用 Controller 功能 - 在需要的地方混合或在 $rootScope 上定义?

angularjs - ng-click angularjs 上的表单验证

node.js - AngularJS:Karma + Jasmine 使用 _real_ 后端进行测试

node.js - NodeJS/Puppeteer - 按标签名称获取元素列表

javascript - 跨浏览器/站点/域脚本之间有什么区别?

javascript - 动态创建的元素上的事件绑定(bind)?

javascript - Angular : Filter Multiple Items

angularjs - 如何将一个类分配给一个报告,而不是奇数行,偶数行,而是日期列的变化?

javascript - 有没有办法使用 Grunt.js 在 Windows 上的 git shell 中调用命令