Javascript 如果一个线程中有多个异步函数,异步函数的执行顺序是什么?

Javascript 如果一个线程中有多个异步函数,异步函数的执行顺序是什么?,javascript,asynchronous,single-threaded,Javascript,Asynchronous,Single Threaded,我正在学习javascript中异步函数的概念。我知道javascript是单线程的,回调函数放在线程中同步可执行代码的后面。这篇文章解释得很好。 但是这篇文章没有解释我的一个问题,如果代码中有多个回调函数呢?例如,下面的代码,执行顺序是什么?是先执行异步函数1还是先执行异步函数2?提前谢谢你 var request = require('request'); // async function 1: take 200ms request('http://sohamkamani.com',

我正在学习javascript中异步函数的概念。我知道javascript是单线程的,回调函数放在线程中同步可执行代码的后面。这篇文章解释得很好。

但是这篇文章没有解释我的一个问题,如果代码中有多个回调函数呢?例如,下面的代码,执行顺序是什么?是先执行异步函数1还是先执行异步函数2?提前谢谢你

var request = require('request');

// async function 1: take 200ms
request('http://sohamkamani.com', function (error, response, body) {
  console.log(body);
})

// async function 2: take 100ms
request('http://facebook.com', function (error, response, body) {
  console.log(body);
})

console.log('I come after the request');


请求将按照您编码的顺序启动。请求
http://sohamkamani.com
将被发送,然后将请求发送到
http://facebook.com
。但是您无法知道回调的顺序,因为它们只会在服务器响应时执行,您不知道何时执行


关于代码的输出,您唯一可以确定的是,
我在请求之后出现
将是写入控制台的第一件事,这将发生在两个请求发送之后,但在它们的回调执行之前。

根据您对事件的描述,下面是事情将如何发生的大致情况。这里的重要概念涉及异步处理、调用堆栈和事件队列

  • 您的脚本(我们称之为
    main.js
    )将添加到调用堆栈中。您的调用堆栈现在如下所示:

    • main.js
  • main.js开始执行。第一行被添加到调用堆栈中。您的调用堆栈现在如下所示:

    • 请求(“”,…)
    • main.js
  • 无论何时解析回调,都将执行并跟踪该请求。因为这里没有其他事情要做,所以它从调用堆栈中移除。因此,您的调用堆栈现在如下所示:

    • main.js
  • main.js
    中的下一行被添加到调用堆栈中

    • 请求(“,…)
    • main.js
  • 同样,无论何时解析回调,都会执行并跟踪请求。它将从调用堆栈中删除

    • main.js
  • 下一行被添加到调用堆栈中

    • log('我在请求之后')
    • main.js
  • 这可以立即执行,并将请求发送到您的控制台以记录这句话。您的调用堆栈现在如下所示:

    • main.js
  • main.js
    完成后,可以将其从调用堆栈中删除。您的调用堆栈现在为空

  • facebook请求在100毫秒后得到解决。回调函数
    函数(错误、响应、主体){…}
    被添加到事件队列中。事件队列中的内容只能在清除调用堆栈后执行

  • 您的调用堆栈已清除!facebook回调函数被添加到调用堆栈中并执行。控制台日志将被发送。回调函数将从调用堆栈中删除

  • 200毫秒后,sohamkamani.com解析并将其回调函数发送到事件队列。您的调用堆栈已清除!回调函数被添加到调用堆栈、执行并从调用堆栈中删除


  • 我认为这几乎是正确的,但真正的细节是回调函数将添加到事件队列中,以便在清除调用堆栈后按顺序执行。是的,如果两个请求同时返回@Nick,我认为这是一种边缘情况,但更大的一点是,我们不知道情况是否如此,所以我们不知道回调的顺序。这是一个很好的解释。谢谢你,尼克和马克!需要注意的是,回调函数进入事件队列,只有在清除调用堆栈后才能执行。换句话说,无论这些请求的解决速度有多快(即使是瞬间),都不可能在
    console.log(body)
    之前发生
    console.log(“我在请求之后出现”)另一个小细节是,只有在收到响应后,才会将这些回调推送到队列中。这意味着可能会有更多(甚至是异步)代码填充队列并提前运行。