Javascript回调背后的机制是异步的

时间:2013-09-29 16:25:28

标签: javascript node.js asynchronous callback

我在理解JS回调的机制时遇到了一些麻烦。我很清楚如何在JS中使用回调,但我不明白回调是如何异步的。

例如,如果我的理解是正确的,那么回调的性质如下:

db.query(param1, param2 , callback_fn1(){..} );

db.query()的实现与以下几行有关:

 db.prototype.query = function(p1 , p2 , callback ){
      //some code 
      callback();
}

上述实现如何使db.query成为异步函数?这是否意味着将名为callback的函数传递给query并在query内调用该函数?看起来query只是另一个同步函数。有人能帮我理解我在这里俯瞰的东西吗?谢谢!

2 个答案:

答案 0 :(得分:3)

您显示的代码示例实际上仍然是同步的,因为它被指示立即运行。异步回调是一个不需要立即执行的回调,所以在你指示它运行之前它不会阻塞事件循环。

Node.js中最常用的方法是使用process.nextTick(),它在事件循环调用堆栈为空时运行指定的函数。这是一个例子:

var async = function(args, callback) {
  // do some work
  process.nextTick(function() {
    callback(val);
  });
};

然后我们调用这样的函数:

async(args, function(val) {
  console.log(val);
});
console.log('end');

在此示例中,函数async()console.log('end')被添加到调用堆栈中。一旦这两个函数都运行,调用堆栈就会清空,一旦它为空,console.log(val)就会运行。

如果您仍然感到困惑,请将process.nextTick()视为此代码的优化版本:

var fn = function() {};
setTimeout(fn, 0);

它基本上意味着“当你不忙时尽快运行这个功能”。

答案 1 :(得分:2)

编辑:我刚才意识到问题是用node.js标记的。我的答案更多是关于浏览器中的Javascript,@ hexacyanide的答案更多是关于node.js.不过我想知道两者都没有受伤!

你发布它的方式代码确实会阻塞。对于异步行为,您可以使用一些内容,例如

  • setTimeoutsetInterval
  • 内置的异步方法,例如来自FileReader API
  • Ajax请求
  • 网络工作者(见@html5rocks

您的示例代码可以编写如下(fiddle):

function doStuff(callback) {
    setTimeout(function () {
        for (var i = 0; i < 1000; i++) {
            // do some busy work
            var x = Math.sqrt(i);
        }

        callback();
    }, 0);
}

console.log('start');
doStuff(function () {
    console.log('callback called');
});
console.log('after doStuff()');

setTimeout调用将允许Javascript解释器/编译器(但是这些天它们确切地工作)以非阻塞事件运行该函数,这就是为什么(最有可能),您将看到输出

start
after doStuff()
callback called

请注意,异步与多线程不同。 Javascript仍然是单线程的(网络工作者除外!)。

可以找到更深入的解释,例如here

相关问题