【问题标题】:Synchronous vs Asynchronous Nodejs同步与异步 Nodejs
【发布时间】:2015-07-07 14:26:35
【问题描述】:

我在使用 Mocha 测试框架自动化网页时,遇到了同步和异步代码这两个术语。 当您发送 HTTP 请求时,我熟悉同步和异步事件……但我从未听说过代码是同步和异步的。 任何人都愿意解释...我在之前的问题中看到它与回调有关,但即便如此我仍然对这个概念感到很困惑。

【问题讨论】:

标签: javascript node.js asynchronous automation synchronous


【解决方案1】:

以下是我的服务器代码的简化版本。我演示了 同步 代码(在您开始执行操作后,在完成之前不会开始进一步的操作)和 异步 代码(您开始执行操作,然后继续执行其他操作,稍后您“回调”或从第一个操作中获取结果。)

这有一些重要的后果。几乎每次调用异步函数时:

  • 你的异步函数的返回值是没有用的,因为该函数会立即返回,虽然查找结果需要很长时间。

  • 您必须等到回调函数执行后才能访问结果。

  • 调用异步函数之后的代码行将在异步回调函数运行之前执行。

举个例子,我下面代码中console.logs的顺序是:

line 3 - before sync
line 8 - after sync, before async
line 16 - after async call, outside callback
line 14 - inside async call and callback



// synchronous operations execute immediately, subsequent code
// doesn't execute until the synchronous operation completes.
console.log('line 3 - before sync');
var app = require('express')();
var cfgFile = require('fs').readFileSync('./config.json');
var cfg = JSON.parse(cfgFile);
var server = require('http').createServer(app);
console.log('line 8 - after sync, before async');

// When you call an asynchronous function, something starts happening,
// and the callback function will be run later:
server.listen(cfg.port, function(){
  // Do things that need the http server to be started
  console.log('line 14 - inside async call and callback');
});
console.log('line 16 - after async call, outside callback');

【讨论】:

  • 顺便说一句,要实际运行你应该运行npm install express的示例,用示例代码创建一个app.js,在它旁边创建一个包含{"port": 3000}config.json文件,最后运行@987654326 @。您也可以尝试编写自己的脚本来调用异步函数setTimeout(callbackFunction, timeInMs)
  • 好吧,这感觉有点熟悉,这基本上是并发正确的??一个代码等待另一个代码发出信号。
  • 或者等等我可能是错的......因为你说异步函数之后的行将在异步函数执行之前执行。 o_0
  • 异步函数是节点如此擅长并发的原因。这就是为什么第 16 行在第 12 行而不是第 14 行之后执行的原因。当解析器到达第 12 行时,它确实调用了 server 对象的 listen 方法(由节点内置的 http 库提供。) listen 函数将立即开始与您的操作系统的网络 API 通信,但这需要一段时间,所以 listen 函数然后返回。当操作系统完成它的工作并且服务器正在监听时,监听函数调用它的回调(我们在第 12-15 行定义并传入的函数。)
【解决方案2】:

同步代码将严格逐行处理,而异步代码将继续下一行,而前几行代码仍在处理中。

对于异步代码,在下面的 sn-p 中,您希望 WorldHello 之前记录到控制台,因为数据库查询需要更多的计算机资源,因此需要更多时间。 console.log('World') 将在查询之前完成执行。

var Person = mongoose.model('Person', personSchema);

Person.findOne({ 'name.last': 'Ghost' }, function(err, person) {
  if(err) 
    throw err;
  else
    console.log('Hello');
});

console.log('World');

在同步代码中,Hello 将在 World 之前记录,因为查询在执行任何后续行之前完成执行。

【讨论】:

    【解决方案3】:

    同步代码基本上意味着代码行是按照它们编写的顺序执行的。同步事件将立即执行关联的回调,就像直接调用函数一样,因此最终结果是相同的。

    一般来说,异步代码是独立于调用代码并发执行的。例如调用 setTimeout 将立即返回并执行下一个表达式,但它会启动一个操作,在未来的某个时间它将触发一个调用指定回调的 异步事件

    Mocha 测试框架支持这两种类型的代码,它为异步代码提供 done() 回调。 done() 是让 Mocha 知道测试何时完成的回调。

    异步测试代码,来自http://mochajs.org/

    describe('User', function() {
      describe('#save()', function() {
        it('should save without error', function(done) { // done is a callback
          var user = new User('Luna');
          user.save(function(err) { // save is async db call that starts here, completes whenever
            if (err) throw err;
            done();
          });
        });
      });
    });
    

    测试同步代码不需要done(),测试代码是按顺序执行的。所以当最后一个表达式被执行时,测试就结束了。

    【讨论】:

      猜你喜欢
      • 2014-01-05
      • 2019-06-14
      • 2013-08-01
      • 2016-12-14
      • 2015-02-23
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 2017-01-09
      相关资源
      最近更新 更多