javascript - 如何使这个 Node.js 程序异步?

标签 javascript node.js asynchronous

在下面的javascript程序中(欧拉问题5)我正在练习编写异步/非阻塞函数。该程序试图找到能被数字 1-10 整除的最小数字。 2520 是第一个最小的,这是程序应该停止的地方。

我设置了程序,以便如果函数一起运行,则应首先完成第二个 checkNum 并先打印第二个,然后打印第一个,但这种情况没有发生?

如何让函数同时运行,而不是一个接一个地运行?我期望我调用的第二个 checkNum 函数的回调首先被调用(因为它开始更接近答案),然后是第一个,但事实并非如此。非常感谢!

var divides = function(a, b) {
  return b % a == 0;
 };

function checkNum(counter, callback) {
   var noRemainder = 0;
   var forward = true;
    while (forward)
    {
    for (var i = 1; i <= 10; i++) {
         if (divides(i, counter))
          { noRemainder++; }
     }

    if (noRemainder == 10) {
       console.log(counter);
       forward = false;
       callback(counter);
    } else {
      console.log(noRemainder);
      noRemainder = 0;
      counter++;
      console.log(counter);
    }
  }
}

checkNum(1, function(counter) {
             setTimeout(function(){
                        console.log("The counter is: " + counter)},3000) 
              }
);

checkNum(2500, function(counter) {
               setTimeout(function(){
                          console.log("The counter2 is: " + counter) },3000)       

                }
);

最佳答案

因为 checkNum 是一个纯粹受 CPU 限制的函数 - 也就是说,它所做的唯一事情就是在紧密循环中执行计算 - 没有理由使其异步。根据定义,该功能是同步的;在计算完成之前,控制权不会返回给调用者。考虑以下异步样式:

checkNum(n, function(err, result) {
    console.log(result);
});
console.log('Next line');

...和同步风格:

console.log( checkNum(n) );
console.log('Next line');

在这两种情况下,checkNum 的结果都将打印在“下一行”之前。即使在异步风格中,直到 checkNum 调用其回调并且回调完成之后才返回控制。 (将此与真正的异步函数进行比较,其中“下一行”将在回调获取结果之前打印。)

Node 的真正魔力来自于这样一个事实:大多数昂贵操作(例如 I/O)是由 native 代码在单独的线程上执行的,当它们完成时,它们会调用 JavaScript主线程回调。因此,执行 JavaScript 所花费的时间非常少,因此您的应用程序性能非常出色。

但是,如果您发现自己在 JavaScript 中编写了像这样昂贵的循环和计算,则必须记住,您将在函数运行的时间内阻塞一切。其他线程上发生的事情将排队,并且您的应用程序代码将没有机会执行任何操作,直到昂贵的函数返回。

有多种方法可以解决此限制(按性能顺序排列):

  • 将计算分解为多个 block 并使用 nextTick开始对每个 block 进行处理。这允许任何排队的事件在 block 之间进行处理。
  • 将计算函数移至单独的文件中,并启动一个新进程来实际进行计算。这使得您的主应用程序在等待结果时可以正常运行。您需要使用 fork因为它带有内置 IPC,所以可以做到这一点。 Here's an example fibonacci calculator.请记住,这确实会带来开销:启动新 Node 进程需要约 30 毫秒和至少 10 MB 的 RAM。
  • Actually run your JavaScript code on a separate thread.请注意,代码将与应用程序的其余部分隔离运行;您的线程将无法访问主应用程序中的任何变量。这与进程 fork 方法非常相似,但速度更快,因为您避免了生成新进程的开销。
  • 使用 native (C++) 代码进行计算,您可以在单独的线程上自由地进行计算。 Here's a native fibonacci example.

关于javascript - 如何使这个 Node.js 程序异步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19128286/

相关文章:

javascript - Moment.js 插件我应该安装这两个依赖项吗?

node.js - 使用Webpack打包ES6模块

javascript - Angular 形式在范围内不可用

javascript - jQuery 选择器未选择对象

javascript - 在NodeJS中,如何从不同字段名的mongodb输出结果?

node.js - 聚合函数返回 null GraphQL

javascript - Mongo 会处理我的服务吗?

PHP cURL 同步和异步

javascript - 默认情况下大多数 http 请求都是同步的吗?

javascript - 如何将时间戳转换为 javascript 日期对象?