【问题标题】:node.js and asynchronous programming palindromenode.js 和异步编程回文
【发布时间】:2013-06-10 00:30:34
【问题描述】:

这个问题可能是重复的。我是 node.js 和异步编程回文的菜鸟。我在谷歌上搜索并看到了很多这方面的例子,但我仍然有点困惑。

好的,从谷歌搜索我了解到所有回调都是异步处理的。 例如,让我们从 node.js api 中获取 readfile 函数

fs.readFile(filename, [options], callback) // 这里的回调会异步处理 fs.readFileSync(文件名,[选项])

  var fs = require('fs');

    fs.readFile('async-try.js' ,'utf8' ,function(err,data){
        console.log(data);   })

    console.log("hii");

上面的代码会先打印 hii 然后再打印内容 文件。

所以,我的问题是:

  1. 是否所有回调都异步处理?
  2. 以下代码不是异步的,为什么以及如何制作它

    function compute(callback){
     for(var i =0; i < 1000 ; i++){}
     callback(i);
    
    }
    
    function print(num){
     console.log("value of i is:" + num);
    }
    
    
    compute(print);
    console.log("hii");
    

【问题讨论】:

    标签: javascript node.js asynchronous


    【解决方案1】:

    所有回调都是异步处理的吗?

    不一定。一般来说,它们是,因为在 NodeJS 中,它们的真正目标是在长时间运行的任务完成(通常是 IO 操作)后恢复函数的执行(continuation)。但是,您为自己编写了一个 同步 回调,因此您可以看到它们并不总是异步的。

    以下代码不是异步的,为什么以及如何实现?

    如果你希望你的回调被异步调用,你必须告诉 Node 在“有时间的时候”执行它。换句话说,您将回调的执行推迟到以后,Node 将完成正在进行的执行。

    function compute(callback){
     for (var i = 0; i < 1000; i++);
    
     // Defer execution for later
     process.nextTick(function () { callback(i); });
    }
    

    输出:

    hii
    value of i is:1000
    

    有关异步回调如何工作的更多信息,请阅读this blog post that explains how process.nextTick works

    【讨论】:

      【解决方案2】:

      不,这是一个常规的函数调用。

      除非强制,否则回调不会是异步的。一个好的方法是在 0 毫秒的 setTimeout 内调用它,例如

      setTimeout(function() { 
         // Am now asynchronous
      }, 0);
      

      通常,当调用函数涉及在服务器上发出新请求(例如打开一个新文件)时,回调是异步的,并且在等待它完成时停止执行是没有意义的。

      【讨论】:

      • 你的意思是在上面的例子中我必须在 setTimeout 中调用 compute(print)。 setTimeout(计算(打印), 0);
      • @RushabhRajeshKumarPadalia 是的,因为setTimeout 的回调是异步的,一旦线程可用就会立即执行。尽管您必须将其包装在匿名函数中以传递参数,例如setTimeout(function() { compute(print) }, 0);
      【解决方案3】:

      以下代码不是异步的,为什么以及如何实现?

      function compute(callback){
        for(var i =0; i < 1000 ; i++){}
        callback(i);
      }
      

      我将假设您的代码试图说:“我需要执行 1000 次操作,然后在一切完成后使用我的回调”。

      即使你的 for 循环在这里也不起作用,因为想象一下:

      function compute(callback){
        for(var i =0; i < 1000 ; i++){
          DatabaseModel.save( function (err, result) {
            // ^^^^^^ or whatever, Some async function here.
            console.log("I am called when the record is saved!!");
          });
        }
        callback(i);
      }
      

      在这种情况下,您的 for 循环将执行保存调用,不会等待它们完成。因此,在您的示例中,您可能会得到类似的输出(取决于时间)

      I am called when the record is saved
      hii
      I am called when the record is saved
      ...
      

      为了让您的计算方法仅在一切真正完成时调用回调 - 所有 1000 条记录都已保存在数据库中 - 我会查看 async Node 包,它可以为您轻松完成此操作,并且为您将在 Node 中面临的许多异步问题提供模式。

      因此,您可以将计算函数重写为:

      function compute(callback){
        var count = 0
        async.whilst(
           function() { return count < 1000 },
           function(callback_for_async_module) {
              DatabaseModel.save( function (err, result) {
                  console.log("I am called when the record is saved!!");
                  callback_for_async_module();
                  count++;
              });
           },
           function(err) {
             // this method is called when callback_for_async_module has
             // been called 1000 times
      
             callback(count);
        );
        console.log("Out of compute method!");
      }
      

      请注意,您的计算函数的回调参数将在console.log("Out of compute method") 之后的某个时间被调用。此函数现在是异步的:应用程序的其余部分不会等待 compute 完成。

      【讨论】:

        【解决方案4】:

        您可以将每个回调调用置于一毫秒的超时内,这样当有空闲线程并且所有同步任务完成时,它们将首先执行,然后处理器将通过想要的超时堆栈工作执行。

        【讨论】:

          猜你喜欢
          • 2014-04-29
          • 2017-03-20
          • 2013-04-26
          • 2011-09-22
          • 2018-12-26
          • 2015-11-06
          • 2013-12-15
          • 2012-06-03
          相关资源
          最近更新 更多