【问题标题】:node.js: How asynchronous are Async loops really?node.js:异步循环到底有多异步?
【发布时间】:2012-08-21 18:18:59
【问题描述】:

我想异步迭代一个数组来解除阻塞。我正在使用 caolan/async 来实现这一点。测试这段代码时:

var ASync = require('async');

var arr = [];
for (var i = 0; i< 10; i++) {
    arr[i] = i;
}

var buf = "howdy";
ASync.forEach(arr, function(item, callback) {
    buf += item;
    callback();
}, function(err) {
    console.log(buf); // in the end
});
buf += "finished";

它显示了这个结果:

howdy0123456789

我认为它应该显示

howdyfinished0123456789

因为我希望异步库推迟执行。但为什么不是呢?

【问题讨论】:

  • 我在这里阅读的关于该主题的一些答案建议使用setTimeout(...,0) 解决方法将执行交回主事件循环,但我真的不喜欢这个想法 - 那样你可以实际使用无论如何,JS 的内置 Array.forEach 方法。此外,我希望 Async 模块会在必要时执行此操作,并向我隐藏这些细节。

标签: node.js asynchronous


【解决方案1】:

在您的代码中,callback 在与foreach 本身相同的事件循环迭代中执行。由于您永远不会超出当前的事件循环迭代,buf += "finished" 仅在所有 buf += item 都被执行后执行。

正确的版本是

var ASync = require('async');

var arr = [];
for (var i = 0; i< 10; i++) {
    arr[i] = i;
}

var buf = "howdy";
ASync.forEach(arr, function(item, callback) {
    process.nextTick(function () {
        buf += item;
        callback();
    });
}, function(err) {
    console.log(buf); // in the end
});
buf += "finished";

最后,buf 将等于howdy0finished123456789。

但是,这项任务过于简单。为什么需要异步循环?

  1. 并行执行异步任务。首先,由于每个任务都是异步的,因此无论如何您都不会在同一个事件循环迭代中触发callback,而是将其交给特定的异步任务。其次,async.parallel更适合这种任务。

  2. 执行一些 CPU 密集型任务,避免冻结事件循环(以便 Node 可以在迭代之间处理一些任务)。这就是我在上面的代码示例中所假设的。使用普通的 JS(及其内置的 Array.prototype.forEach)来完成这项任务将非常困难,因为您需要以某种方式实现对事件的检测,循环的所有迭代都已处理。

【讨论】:

  • 很好,但“tick 处理”不正是像 Async 这样的库应该对用户隐藏的吗?无论如何,Async 中的迭代函数有什么优势:Array 原型上的 forEach 方法在这种情况下也做得很好...... Step.js 做得“更好”吗?
  • async 向您隐藏所有任务都已完成的事件检测逻辑。如果您想将任务的某些特定部分卸载到事件循环的另一个迭代中,请明确说明;这没什么大不了的。
  • 在底层,async 使用内置的Array.prototype.forEach。您可以在此处查看async 添加的内容:github.com/caolan/async/blob/master/lib/async.js#L79
【解决方案2】:

我认为您应该阅读以下内容: http://howtonode.org/understanding-process-next-tick

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-11
    • 1970-01-01
    • 2015-02-27
    • 2017-06-16
    • 1970-01-01
    • 2018-10-17
    • 2014-02-06
    • 1970-01-01
    相关资源
    最近更新 更多