22

我正在尝试掌握 Javascript 异步函数和回调。

我陷入了回调函数的概念,我正在阅读一些地方:它们用于顺序执行代码(主要是在 jquery 的上下文中,例如 animate)和一些特别是在 Nodejs 的上下文中的地方;它们用于并行执行异步并避免代码阻塞。

那么这个主题的一些专家能否阐明这一点并清除我脑海中的这个模糊(例子??)。所以我可以考虑使用回调函数

或者这完全取决于您在代码中调用/放置回调函数的位置?.

谢谢,

PS:我担心这个问题会很主观,但我仍然可以期待具体的答案(也许是一些例子)

编辑:实际上这是来自互联网的例子,这让我模棱两可:

function do_a(){
  // simulate a time consuming function
  setTimeout( function(){
    console.log( '`do_a`: this takes longer than `do_b`' );
  }, 1000 );
}

function do_b(){
  console.log( '`do_b`: this is supposed to come out after `do_a` but it comes out before `do_a`' );
}

do_a();
do_b();

结果

`do_b`: this is supposed to come out after `do_a` but it comes out before `do_a`
`do_a`: this takes longer than `do_b`

根据我的理解,当 JS 是顺序的时, do_b 应该总是在 do_a 之后。

4

3 回答 3

27

JavaScript 的核心在很大程度上是同步的,因为函数在完成之前完全完成了它们的任务。在 AJAX 出现之前,实际上只有 setTimeout 和 setInterval 提供了异步行为。

但是,很容易忘记事件处理程序实际上是异步代码。附加处理程序不会调用处理程序代码,并且直到将来某个不可知的时间才会执行该代码。

然后是 AJAX,它调用服务器。这些调用可以配置为同步调用,但开发人员通常更喜欢异步调用并使用回调方法来实现它们。

然后,我们看到了 JS 库和工具包的激增。这些努力使不同浏览器的事物实现同质化,并建立在异步代码的回调方法之上。您还开始看到更多用于数组迭代或 CSS 查询结果处理之类的同步回调。

现在,我们看到了 Deferreds 和 Promises 的混合。这些对象代表长时间运行的操作的值,并提供 API 用于在该值到达时处理该值。

NodeJS 倾向于对许多事情采用异步方法;这是真的。然而,这更多是他们的设计决定,而不是 JS 的任何固有异步性质。

于 2013-05-13T14:14:30.140 回答
14

Javascript 始终是一种同步(阻塞)单线程语言,但我们可以通过编程使 Javascript 行为异步。

同步代码:

console.log('a');
console.log('b');

异步代码:

console.log('a');
setTimeout(function() {
    console.log('b');
}, 1000);
setTimeout(function() {
    console.log('c');
}, 1000);
setTimeout(function() {
    console.log('d');
}, 1000);
console.log('e');

这输出: aebcd

于 2015-05-10T20:06:32.560 回答
3

在节点中,长时间运行的进程用于process.nextTick()对函数/回调进行排队。这通常在节点的 API 中完成,除非您的编程(在 api 之外)使用阻塞的东西或长时间运行的代码,否则它不会对您产生太大影响。下面的链接应该能更好地解释它。

howtonode process.nextTick()

jQuery AJAX 还接受回调,例如它的编码在继续下一个代码块之前不等待服务器响应。它只是记住服务器响应时要运行的函数。这是基于浏览器公开的 XMLHTTPRequest 对象。XHR 对象会记住响应返回时要回调的函数。

setTimeout(fn, 0)一旦调用堆栈为空(下一个可用的空闲刻度),javascript 将运行一个函数,该函数可用于创建类似异步的功能。关于stackoverflow的setTimeout(fn,0)问题

总结 javascript 的异步能力与它们编程的环境和 javascript 本身一样多。除非您使用某些 API/脚本,否则仅使用大量函数调用和回调不会获得任何魔力。

Jquery Deferred Object是 jQuery 异步功能的另一个很好的链接。谷歌搜索可能会为您找到有关 jQuery Deferred 如何工作的信息,以获得更多洞察力。

于 2013-05-13T14:14:29.030 回答