gpt4 book ai didi

javascript - 事件循环更喜欢微任务队列而不是回调队列?

转载 作者:太空宇宙 更新时间:2023-11-04 15:25:22 25 4
gpt4 key购买 nike

我正在测试 JS 中异步代码的概念。对回调队列和微任务队列顺序感到困惑。每当 Promise 对象被解析时,履行方法 { then } 就会被推送到微任务队列中,而浏览器定时器函数(例如 setTimeout)的回调会被推送到回调队列中。事件循环不断检查队列,并在调用堆栈变空时将函数从队列插入调用堆栈。事件循环应该优先选择微任务队列而不是普通回调队列,但在示例中:https://jsfiddle.net/BHUPENDRA1011/2n89ftmp/否则就会发生这种情况。

function display(data) {
console.log('hi back from fetch');
}

function printHello() {
console.log('hello');
}

function blockfor300ms() {
for (let i = 0; i < 300; i++) {
// just delaying logic
}
}
// this sets the printHello function in callback queue { event loop queue }
setTimeout(printHello, 0);

const futureData = fetch('https://api.github.com/users/xiaotian/repos');
// after promise is resolved display function gets added into other queue : Microtask queue { job queue}
futureData.then(display);
// event loop gives prefrence to Microtask queue ( untill its complete)

blockfor300ms();
// which runs first
console.log('Me first !')

预期输出

  • 我先!
  • 嗨,从 fetch 回来
  • 你好

实际输出:

  • 我先!
  • 你好
  • 嗨,从 fetch 回来

请告诉我这里发生的情况。

谢谢

最佳答案

虽然这是真的,但“kib”所说的是:

"your function blockfor300ms doesn't block the thread long enough forthe fetch to receive a response"

遗憾的是,这是无关紧要的,因为即使您在收到对 fetch 调用的响应之前阻止执行,您仍然会看到相同的结果......(请参阅下面的示例代码片段,您可以使用警报框或非异步 XMLHttpRequest 调用的长循环来阻止执行,我收到了相同的结果)

不幸的是,fetch 并不像我发现的所有博客和资源所描述的那样工作......其中指出

Fetch will add it's promise chain to the micro-tasks queue and run before any callbacks on the next tick of the event loop.

从下面的示例代码中可以看出,fetch 并不像其他人所描述的那样简单地将其解析处理程序函数添加到微任务队列,因为正如 Lewis 所说,由于它需要网络事件,所以它正在被由网络任务源处理。但是,我不认为这是由于 printHello“阻塞”网络任务,因为在下面的示例代码中 fetch 是在 printHello 之前触发的,并且网络响应也会在计时器完成之前发生。

正如您在下面的示例中看到的,在收到获取响应后(2000 毫秒),我将 printHello 延迟添加到任务队列中,但是如果我们阻止代码执行的时间超过 2000 毫秒(因此,仍在运行执行上下文),那么将首先打印“Hello”。这意味着 fetchresolve() 处理程序并不是简单地添加到微任务队列中,它会与其他 Promise 处理程序一起触发。

那么,如果在计时器任务完成之前(2000 毫秒)收到响应并理论上将其添加到任务队列中,为什么在回调之后仍然会记录它? 好吧,我的猜测是定时器任务源的优先级必须高于网络任务源的优先级。因此,两者都位于任务队列中,但计时器任务队列在网络任务队列之前触发...

规范链接:

定时器任务源 - https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-task-source网络任务源 - https://html.spec.whatwg.org/multipage/webappapis.html#networking-task-source

function display(data){console.log("Fetch resolved!")}
function printHello(){console.log("Callback Time")}
function blockExecution() {
console.log("Blocking execution...");
alert('Wait at least 2000ms before closing');
}

const futureData = fetch('https://jsonplaceholder.typicode.com/todos/1');
futureData.then(response => response.json()).then(display);

setTimeout(printHello, 2000);

const p = new Promise(
// this is called the "executor"
(resolve, reject) => {
console.log("I'm making a promise...");
resolve("Promise resolved!");
console.log("Promise is made...");
}
);

p.then(
// this is called the success handler
result => console.log(result)
);

blockExecution();

console.log("Execution ended!");

关于javascript - 事件循环更喜欢微任务队列而不是回调队列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50754030/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com