node js是异步/同步进程,非阻塞/阻塞IO

时间:2013-09-25 03:22:07

标签: node.js asynchronous blocking nonblocking synchronous

nodejs中的异步进程是什么?看看我的测试。

+ Person.find(): query on database, it will take time
+ while(): delay for 5s

结果在控制台中就像这个序列:

the first:  Listening on port 3000
the second: Wait
----third:  0
---------:  4
---------:  2
---------:  2
---------:  3
---------:  1
---------:  1

如果我们说这是异步过程,为什么程序在运行console.log('0')和console.log('4')之前在5s内停止while()函数?

var Product = mongoose.model('Product', ProductSchema);
var myObject = new Object();

Person.find().exec(function (err, docs) {

    for (var i=0;i<docs.length;i++)
    { 
        Product.find({ user: docs[i]._id},function (err, pers) {
             myObject[i] = pers;
             console.log('1'); 
            });
        console.log('2'); 
    }
    console.log('3'); 
});
console.log('Listening on port 3000'); 
var startTime = new Date().getTime();
console.log('wait');
while (new Date().getTime() < startTime + 5000); //the program stop here for 5s before priting 
console.log('0');                                //console.log('0') and console.log('4');

app.listen(3000);
console.log('4');

2 个答案:

答案 0 :(得分:0)

Node在一个进程上工作,但能够切换到本机代码进行某些异步处理除外。这些通常是I / O调用,如网络和电话。 Db访问。

您的while (new Date().getTime() < startTime + 5000);会阻止。但是,请查看Product.find()来电。你传递了一个回调函数。处理回调函数的代码是异步的,会在I / O完成时通知您。

答案 1 :(得分:0)

您获得此执行顺序的原因是因为您展示的唯一异步功能是Person.find().exec()Product.find()

您看到的顺序是:

  1. 您的变量实例化是同步的。
  2. Person.find().exec()是异步的,不会阻止主线程。
  3. 主线程未被阻止,因此console.log('Listening on port 3000')会运行。
  4. console.log()是同步的,因此var startTime已设置。
  5. console.log('wait');是同步的,并在执行后继续。
  6. while()循环运行。 阻止主线程。
  7. 事件循环恢复,正在运行console.log('0');
  8. listen()console.log('4')函数同步运行。
  9. Person.find().exec()最终运行并启动for循环。
  10. for循环也阻止。所有迭代都在继续之前完成。
  11. 由于循环已停止阻塞主线程,因此运行console.log('3')
  12. 循环中异步函数的回调执行。
  13. 总结一下,您的程序在while()循环处停止,因为循环正在阻塞。如果要延迟代码的执行,请在不使用全局定时器函数之一阻止主线程的情况下执行此操作:

    setTimeout(function() {
      console.log('0');
    
      app.listen(3000);
      console.log('4');
    }, 5000);