2014-02-19 33 views
2

我正在学习Node.js,我在每个教程中听到的都是“Node is asynchronous and no-blocking!”所有的Node.js回调函数都是异步的吗?

我听说过在常规的浏览器JavaScript中,只有某些东西,如AJAX调用可以是异步或非阻塞的(使用回调)...... Node.js也是如此,或者都是Node.js回调函数使异步/非阻塞?

+1

是的。这是javascript的本质,不是node.js的具体情况。 – zsong

+6

@zsong这并不完全准确。 – Brad

+1

这是完全不准确的。阅读规格。没有关于同步/异步或阻塞/非阻塞或io – vkurchatkin

回答

1

不,它们不会自动异步。考虑以下代码:

function foo(array, filter, callback) { 
    var result = [] 
    for (var i = 0; i < array.length; i++) { 
     if (filter(array[i])) result.push(array[i]); 
    } 

    callback(result); 
} 

现在想象一个这样的程序:

foo([ 1, 2, 3, 4 ], function() { while(true); }, console.log); 
console.log('Blocking?'); 

如果foo将异步然后Blocking?会立刻出现,但它不!


但是,您可以肯定的是,大部分/所有采用回调的标准库都是非阻塞异步代码。其中大部分也有Sync副本。

2

当您将回调传递给某个函数时,您期望该函数可以在其他时间调用您的回调函数。但是,它不会自动异步。

假设我有这样的代码:

function callSomething(callback) { 
    callback(); 
} 

function theCallback() { 
    // Do something time consuming here 
} 

callSomething(theCallback); 

在这种情况下,我们传递一个回调,但回调获取现有的调用堆栈上立刻打电话。这被认为是坏习惯并且是强烈建议在Node.js中使用。如果你想相当立即拨打回调,使用process.nextTick()

function callSomething(callback) { 
    process.nextTick(callback); 
} 

那么直接回答你的问题大多是肯定的。当您在Node.js中为函数指定回调时,按照惯例,它们将在稍后的时间点在另一个调用堆栈上被调用。但是如果你使用了一些不知道如何遵循这个约定的不好的代码,那么这是不能保证的。

+0

一般而言。另外值得一提的是,可以使用'setImmediate',我听说过几个节点核心成员说使用它比'nextTick'更好,以避免'nextTick'特定的问题(主要是IO饥饿) – vkurchatkin

+0

@vkurchatkin有趣的是,我没有没听说过setImmediate。我绝对会在我的一些项目中交换这个! http://stackoverflow.com/a/15349865/362536 – Brad

5

是否所有的Node.js回调函数都是异步/非阻塞的?

不。只有I/O通常是异步的,但许多其他回调是同步的。总是检查文档。的异步函数

实例:

另请参阅Are all javascript callbacks asynchronous? If not, how do I know which are?(包括一些其他示例)。

+1

这不完全准确。你是对的,I/O是多线程的,其余的都不是,但许多其他的回调仍然是异步的,并在一个单独的调用堆栈中调用。 – Brad

+0

你是指什么其他回调? – vkurchatkin

+0

当您将函数作为参数传递时,并不意味着它是回调。 ForEach是迭代器,EventEmitter是监听器 – vkurchatkin