首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这一行代码需要“等待”触发微任务队列处理?

为什么这一行代码需要“等待”触发微任务队列处理?
EN

Stack Overflow用户
提问于 2019-07-02 11:58:40
回答 1查看 2.5K关注 0票数 13

以下引号是理解微任务队列处理的主要引用:

当JS堆栈清空.时处理微任务(承诺使用)。

对我毫无意思。

事件循环的一个循环将从宏任务队列中处理一个任务(这个队列在WHATWG规范中被简单地称为任务队列)。在这个宏任务完成后,所有可用的微任务都将被处理,即在相同的执行周期内.。

现在,关于以下代码段中的第9行(**):

从执行这个代码片段w/调试器开始,在处理/执行这些.then( callback )微任务时,执行堆栈不会显示为空。

f2()这样的常规函数是否被认为是一项任务(也称为宏任务)?(当它返回时,它是一个事件循环nextTick(),微任务队列被处理)

为什么在JS堆栈不是空的时候执行微任务?

代码语言:javascript
复制
function f2() {
    let x = new Promise( (resolve, reject) => { resolve( () => {console.log('howdy')} ) })
    return x
}

async function f1(){
    let y = Promise.resolve().then(() => { console.log('yo1')})
    console.log('yo2')
	let r2awaited =  await f2() //** 'yo0' and 'yo1' log when the interpreter hits this line.
	return r2awaited
}

async function start(){
     let y = Promise.resolve().then(() => { console.log('yo0')})
	let xx = await f1()
	console.log('main call return:')
	console.log(xx)
}
start()

编辑:另一个奇怪的发现--当您在第17行的xx()后面添加console.log(xx)时,堆栈在执行微任务之前是完全清除的。

在微任务队列处理之前的第一步调用堆栈:

接下来的下一步。

在这两个步骤之间,处理了微任务队列。

调用堆栈是否在这些步骤^之间的遮罩下清除?

然后是否根据await [expression]之后的代码所需的词法环境创建了一个新的调用堆栈?

编辑:在发布这篇文章的时候,我不知道铬调试器调用堆栈中-(异步)-(异步)

此“假堆栈”用于异步调试,其方式与同步调试一致。

只有上面的元素-(异步)

EN

回答 1

Stack Overflow用户

发布于 2019-07-02 12:55:02

“当JS堆栈清空时,就会处理微任务(承诺使用)。”-Jake存档(对我来说没有意义)

“调用堆栈”是当前正在执行的内容列表:

代码语言:javascript
复制
function foo() {
  debugger;
  console.log('foo');
}

function bar() {
  foo();
  debugger;
}

bar();

当我们命中第一个调试器语句时,脚本仍然在执行,就像barfoo一样。由于存在父-子关系,所以堆栈是script > bar > foo。当我们命中第二个调试器语句时,foo已经完成执行,因此它不再在堆栈上。堆栈是script > bar

当堆栈变为空时,将处理微任务队列,直到其为空为止。

“事件循环的一次遍历将从宏任务队列中处理一个任务(这个队列在WHATWG规范中被简单地称为任务队列)。在这个宏任务完成后,所有可用的微任务都将被处理,即在相同的回溯周期内。”

编辑:我继续阅读上面的“宏任务”作为“微任务”。浏览器中没有真正的宏任务队列,它只是一个任务队列。

虽然在处理任务后确实有一个微任务处理点,但实际上只有处理将任务排到队列中的规范,而不首先调用JS。大多数情况下,当JS堆栈清空时,微任务队列就会被清空。

当处理/执行这些.then(回调)微任务时,从执行这个代码片段w/调试器开始,执行堆栈就不会显示为空。

在执行回调时,堆栈将永远不会为空,因为回调本身将位于堆栈上。但是,如果这是堆栈上唯一的内容,则可以假设堆栈在调用此回调之前为空。

Chrome的devtools试图帮助维护一个“异步”堆栈,但这不是真正的堆栈。真正的堆栈是第一个“异步”行之前的所有内容。

像f2()这样的常规函数是否被视为一项任务?

作为一个任务或一个微任务不是函数的属性。可以在任务、微任务和事件循环的其他部分(如呈现)中调用相同的函数。例:

代码语言:javascript
复制
function foo() {}

// Here, I'll call foo() as part of the current task:
foo();

// Here, I'll let the browser call foo() in a future task:
setTimeout(foo);

// Here, I'll let the browser call foo() in a microtask:
Promise.resolve().then(foo);

// Here, I'll let the browser call foo() as part of the render steps:
requestAnimationFrame(foo);

在您的示例中,在微任务中不调用f2。就像这样:

代码语言:javascript
复制
function three() {}
function two() {}

async function one() {
  await two();
  three();
}

one();

在这里,在执行脚本的任务中调用one()one()同步调用two(),因此它作为同一任务的一部分运行。然后,我们await调用two()的结果。因为我们是await,所以函数的其余部分在一个微任务中运行。three()被调用,因此它在同一个微任务中运行。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56851983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档