【问题标题】:How do I make this JS function asynchronous?如何使这个 JS 函数异步?
【发布时间】:2011-04-26 14:03:11
【问题描述】:
function takesTime(){

    for (var i = 0; i<some_very_large_number; i++){
        //do something synchronous
    }
    console.log('a');
}

takesTime();
console.log('b');

这打印: 一个 b 你会如何让它打印: b 一个

【问题讨论】:

  • 抱歉没有意识到有这样的事情!

标签: javascript node.js


【解决方案1】:
for (var i = 0; i < someVeryLargeNumber; ++i) {
    setTimeout(function () {
        //do something synchronous
    }, 0);
}

另请参阅setZeroTimeout 以获得每个循环几毫秒的时间,尽管人们在那里所做的工作似乎是基于浏览器的。

【讨论】:

  • 这就是节点(非 C 库)中所有异步函数的底层实现方式?
  • 我很难说;我自己没有看过Node源代码,也不知道你指的是什么示例函数。其他人可能会回答得更好。
  • 在 node.js 中,你应该使用 process.nextTick(function),而不是 setTimeout(function, 0) -- 效率更高。
  • 在较新版本的节点中查看setImmediate
【解决方案2】:

我看到这是标记为 node.js,所以我将从这个角度回答它:你不应该。通常,如果您正在阻塞,它将是:网络绑定(您应该使用和/或重用 network libraries 围绕异步方法),I/O 绑定(您应该使用和/或重用 I/O libraries) ,或受 CPU 限制。您没有为长时间运行的任务提供任何上下文,并且鉴于您有一个包含 some_very_large_number 的循环不变量,我假设您正在想象一些 CPU 密集型任务在一个大字段上迭代。

如果您实际上受 CPU 限制,您应该重新考虑您的策略。 Node 只存在于一个内核上,因此即使您能够使用多线程,您实际上也只是在转动轮子,因为每个请求仍然需要一定量的 CPU 时间。如果您确实打算做一些计算密集型的事情,您可能想考虑使用queuing system,并让其他东西处理更适合处理数据的数据。

【讨论】:

  • 在问题下找到更深层次的问题非常好:)
【解决方案3】:

Javascript 是基于事件的,一切都发生在一个线程中。使其“异步”的方法是使用超时 (setTimeout())。

【讨论】:

  • 为什么“异步”在引号中?异步不等于多线程;这不是“假”异步。
  • 不,但异步意味着在继续之前不等待操作完成。 Javascript 不会那样做。当其他语言这样做时,会使用并发机制(例如,单独的线程/进程/DMA 传输/中断例程)。
  • 这样的笼统陈述肯定是错误的。例如,C# 不使用并发机制(在 C# 5 中,这种异步被嵌入到语言中)。事实上,任何允许回调的语言都可以实现单线程异步。
  • JavaScript 会做到这一点; Ajax 调用(在 Web 上)或 IO 操作(在 Node.js 中)是一个很好的例子,说明 JavaScript 如何在继续之前不会等待操作完成。
  • 并发正在使用中;它只是不在用户代码中。我没有详细说明哪一层(用户代码 vs 语言运行时 vs 库 vs 内核),因为它不是很相关。我故意没有说语言实现了它,我说它正在使用。
【解决方案4】:

您可以使用网络工作者来实现您的目标,但您需要一个单独的 js 文件,并且您必须添加管道代码来发布消息并处理这些消息。

node.js 本身不支持 web worker,但在以下位置提供了一个实现:

https://github.com/cramforce/node-worker/

否则类似如下代码:

var pid = require('child_process').spawn('node', ['childScript.js']) pid.stdout.on('数据',函数(数据){ 控制台.log(数据); }); 控制台.log('b');

childScript.js

for (var i = 0; i

【讨论】:

  • 一个警告:不是所有的浏览器都支持worker;由于 OP 没有指定特定的浏览器,因此最好假设跨浏览器支持很重要。值得注意的是 IE 还不支持工人(但可能在 IE9 中)
  • 是的,对不起,我应该在它前面加上这是 node.js 特定的事实。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-28
  • 1970-01-01
  • 1970-01-01
  • 2017-12-20
  • 1970-01-01
  • 2013-10-17
  • 1970-01-01
相关资源
最近更新 更多