JavaScript 异步回调 - Promise 和 setTimeout [英] JavaScript async callbacks - Promise and setTimeout

查看:58
本文介绍了JavaScript 异步回调 - Promise 和 setTimeout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下代码中:

setTimeout(() => console.log(hello"), 0);Promise.resolve('成功!').then(console.log)

在我的理解中应该发生什么:

  1. setTimeout 被调用 =>print hello 直接加入回调队列,时间为0
  2. Promise.resolve =>打印成功!添加到回调队列

如果我没记错的话,回调队列是FIFO.>

但是代码输出是:

成功!你好

解释是什么?

解决方案

有 2 个单独的队列用于处理回调.一个和一个队列.setTimeoutma​​cro 队列中排队一个项目,同时承诺解析 - 到 micro 队列.当前正在执行的宏任务(在这种情况下是主脚本本身)是同步执行的,一行一行,直到它完成.完成后,循环执行 微任务 队列中排队的所有内容,然后继续 队列中的下一项(在您的情况下是 控制台.log("hello")setTimeout 排队.

基本上,流程如下所示:

  1. 脚本开始执行.

宏任务队列:[],微任务队列:[].

    遇到
  1. setTimeout(() => console.log(hello"), 0); 导致在宏任务队列中推送新项目.

宏任务队列:[console.log(hello")],微任务队列:[].

  1. Promise.resolve('Success!').then(console.log) 被读取.Promise 立即解析为 Success!,并且 console.log 回调被加入到微任务队列中.

MacrotaskQueue: [console.log("hello")], MicrotaskQueue: [console.log('Success!')].

  1. 脚本完成执行,因此在继续宏队列中的下一个任务之前,它会检查微任务队列中是否有内容.
  2. console.log('Success!') 从微任务队列中拉取并执行.

宏任务队列:[console.log(hello")],微任务队列:[].

  1. 脚本再次检查微任务队列中是否还有其他内容.没有,所以它从宏任务队列中获取第一个可用任务并执行它,即 - console.log(hello").

宏任务队列:[],微任务队列:[].

  1. 在脚本执行完 console.log("hello") 后,它会再次检查微任务队列中是否有任何内容.它是空的,所以它检查宏任务队列.它也是空的,所以所有排队的东西都会被执行并且脚本完成.

不过,这是一个简化的解释,因为它可能会变得更加棘手.微任务队列通常主要处理 promise 回调,但您可以自己将代码排入队列.微任务队列中新添加的项目仍然会在下一个宏任务项目之前执行.此外,微任务可以将其他微任务加入队列,这可能导致处理微任务的无限循环.

一些有用的参考资源:

In the following code:

setTimeout(() => console.log("hello"), 0);

Promise.resolve('Success!')
  .then(console.log)

What should happen in my understanding:

  1. setTimeout is called => print hello directly added to callback queue as time is 0
  2. Promise.resolve => print Success! added to callback queue

If I am not wrong, the callback queue is FIFO.

But the code output is:

Success!
hello

What is the explanation?

解决方案

There are 2 separate queues for handling of the callbacks. A macro and a micro queue. setTimeout enqueues an item in the macro queue, while promise resolution - to the micro queue. The currently executing macro task(the main script itself in this case) is executed synchronously, line by line until it is finished. The moment it is finished, the loop executes everything queued in the microtask queue before continuing with the next item from the macro queue(which in your case is the console.log("hello") queued from the setTimeout).

Basically, the flow looks like this:

  1. Script starts executing.

MacrotaskQueue: [], MicrotaskQueue: [].

  1. setTimeout(() => console.log("hello"), 0); is encountered which leads to pushing a new item in the macrotask queue.

MacrotaskQueue: [console.log("hello")], MicrotaskQueue: [].

  1. Promise.resolve('Success!').then(console.log) is read. Promise resolves to Success! immediately and console.log callback gets enqueued to the microtask queue.

MacrotaskQueue: [console.log("hello")], MicrotaskQueue: [console.log('Success!')].

  1. The script finishes executing so it checks if there is something in the microtask queue before proceeding with the next task from the macro queue.
  2. console.log('Success!') is pulled from the microtask queue and executed.

MacrotaskQueue: [console.log("hello")], MicrotaskQueue: [].

  1. Script checks again if there is something else in the microtask queue. There is none, so it fetches the first available task from the macrotask queue and executes it, namely - console.log("hello").

MacrotaskQueue: [], MicrotaskQueue: [].

  1. After the script finishes executing the console.log("hello"), it once again checks if there is anything in the microtask queue. It is empty, so it checks the macrotask queue. It is empty as well so everything queued is executed and the script finishes.

This is a simplified explanation, though, as it can get trickier. The microtask queue normally handles mainly promise callbacks, but you can enqueue code on it yourself. The newly added items in the microtask queue will still be executed before the next macrotask item. Also, microtasks can enqueue other microtasks, which can lead to an endless loop of processing microtasks.

Some useful reference resources:

这篇关于JavaScript 异步回调 - Promise 和 setTimeout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆