异步任务到哪里去执行了

都知道异步请求不会马上执行得到结果,是浏览器新开了一个线程去跑(异步http请求线程),跑完把注册的success回调放到事件队列里面?我不确定是不是这样

阅读 3.3k
3 个回答

是。

只不过这个线程可能不是新开的,而是一直放在那里专门干这个的。

建议了解下 JavaScript的运行机制:

JavaScript的运行机制:

  1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack);
  2. 主线程之外,还存在着“任务队列”。只要异步任务有了运行结果,就会在“任务队列”中放置一个事件;
  3. 一旦“执行栈”中的所有同步任务执行完毕,系统就会读取“任务队列”,其中对应的异步任务,会结束等待状态,进行执行栈,开始执行;
  4. 主线程不断重复第三步。

以上概括:调用站中的同步任务都执行完毕,站内被清空了,就代表主线程空闲了,这个时候就会去任务队列中按照顺序读取一个任务放入到栈中执行。每次栈内被清空,都会读取任务队列有没有任务,有就读取执行,一直循环 读取-执行 的操作。

一个事件循环中有一个或者是多个任务队列
  • JavaScript中两种异步任务:

    • 宏任务:script(整体代码),setTimeout,setInterval,setImmediate,I/O,UI rendering;
    • 微任务:process.nextTick(Node.js),Promise,Object.observe,MutationObserver。

2.事件循环(event-loop)是什么?

主线程从“任务队列”中读取执行时间,这个过程是循环不断的,这个机制被称为事件循环
机制具体如下:主线程会不断从任务队列中按顺序读取任务执行,每执行完一个任务都会检查microtask队列是否为空(执行完一个任务的具体标志是函数执行栈为空),如果不为空则会一次性执行完所有microtask,然后再进入下一个循环去任务队列中读取下一个任务执行。

详细说明:
  1. 选择当前要执行的宏任务队列,选择一个最先进入任务队列的宏任务,如果没有宏任务,则会跳转至microtask的执行步骤;
  2. 将事件循环的当前运行宏任务设置为已选择的宏任务;
  3. 运行宏任务;
  4. 将时间循环的当前运行任务设置为null;
  5. 将运行完的宏任务从宏任务队列中移除;
  6. microtasks步骤:进入mocrotasks检查点;
  7. 更新界面渲染;
  8. 返回第一步。

执行进入 microtask检查点的具体步骤如下:

  1. 设置进入microtask检查点的标志位true;
  2. 当事件循环的微任务队列不为空时:选择一个最先进入microtask队列的microta;
  3. 对于相应事件循环的每个环境设置对象(environment settings object),通知他们哪些promise为rejected;
  4. 清理indexedDB事务;
  5. 设置进入microta检查点的标志为false。
需要注意的是:当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。

[image:19EE9765-9704-46EC-844A-10ACF8EF4D91-348-000037EE76914D21/D6E7E818-B877-4861-BE11-81BC649E3262.png]

3.Event-loop是如何工作的

setTimeout(()=>{
    console.log(“setTimeout1”);
    Promise.resolve().then(data => {
        console.log(222);
    });
});
setTimeout(()=>{
    console.log(“setTimeout2”);
});
Promise.resolve().then(data=>{
    console.log(111);
});

运行结果为:

111
setTimeout1
222
setTimeout2

JS 引擎是如何执行这段代码的:

  1. 主线程上没有需要执行的代码
  2. 首先检查微任务队列,发现此队列不为空,执行第一个promise的then回调;
  3. setTimeout在 0ms 后将回调函数放到宏任务队列中;
  4. 此时的微任务队列为空,进入下一个事件循环,检查宏任务队列,发现有setTimeout的回调函数,立即执行回调函数,进入下一个事件循环;

4.为什么会需要event-loop

因为JavaScript是单线程的。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。为了协调事件(event),用户交互(user interaction),脚本(script),渲染(rendering),网络(networking)等,用户代理(user agent)必须使用事件循环。

新手上路,请多包涵

js单线程,了解下执行栈和任务队列的区别即可,建议看一下高程的解释.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题