为什么这行带有“await”的代码会触发微任务队列处理?

2024-05-18

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

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

- 杰克·阿奇博尔德 https://twitter.com/jaffathecake/status/954653170986311680

这对我来说没有意义。

事件循环的一圈将恰好有一个从宏任务队列(该队列在 WHATWG 规范中简称为任务队列)中处理的任务。该宏任务完成后,将处理所有可用的微任务,即在同一循环周期内。

- 堆栈溢出 https://stackoverflow.com/a/25933985/1541563

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

通过使用调试器逐步执行此代码片段,执行堆栈在以下情况下不会显示为空:.then( callback )微任务被处理/执行。

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

为什么当 JS 堆栈不为空时微任务仍在执行?

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()

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

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

然后立即进行下一步。

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

这些步骤之间的调用堆栈是否清除[在引擎盖下]^?

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

编辑:在发布本文时,我不知道 chrome 调试器调用堆栈中 -----(async)----- 行下方的所有内容都是“假堆栈”的一部分。

这个“假堆栈”以与同步调试一致的方式用于异步调试。

只有该 -----(async)----- 行上方的元素才是真正的主线程调用堆栈的一部分。


“当 JS 堆栈清空时,就会处理微任务(承诺使用)。” -杰克阿奇博尔德(对我来说没有意义)

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

function foo() {
  debugger;
  console.log('foo');
}

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

bar();

当我们点击第一个调试器语句时,脚本仍在执行,如下所示bar, as is foo。由于存在父子关系,所以栈是script > bar > foo。当我们点击第二个调试器语句时,foo已经执行完毕,所以它不再在堆栈上。堆栈是script > bar.

微任务队列被处理直到它为空,此时堆栈变空。

“事件循环的一次循环将恰好从宏任务队列(该队列在 WHATWG 规范中简称为任务队列)中处理一个任务。在该宏任务完成后,将处理所有可用的微任务,即相同的复飞周期。” - 堆栈溢出

Edit:我一直将上面的“宏任务”读作“微任务”。浏览器中实际上并不存在宏任务队列之类的东西,它只是一个任务队列。

虽然处理完任务后确实有一个微任务处理点,​​但它只是真正处理队列任务到队列微任务的规范,而不是先调用JS。大多数时候,当JS堆栈清空时,微任务队列也随之清空。

通过使用调试器逐步执行此代码片段,当处理/执行这些 .then(callback) 微任务时,执行堆栈不会显示为空。

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

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

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

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

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 is not在微任务中调用。有点像这样:

function three() {}
function two() {}

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

one();

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么这行带有“await”的代码会触发微任务队列处理? 的相关文章

  • WebGL iOS 渲染为浮点纹理

    我正在尝试在 iOS Safari 上的 WebGL 中渲染浮点纹理 而不是在本机应用程序中 我已经设法让 iOS 读取手动 例如从 JavaScript 创建的浮点纹理 但是当我创建浮点类型的帧缓冲区并使用 GPU 渲染到其中时 它不起作
  • moment.calendar() 没有时间

    我想使用不带时间的 moment calendar 选项 所以而不是 上周二下午 5 点 我想要 上周二 有人知道 Moment 现在是否有解决方案吗 我找到了这个小提琴http jsfiddle net nawxZ http jsfidd
  • jQuery - 将所有展开的文本包装在 p 标签中

    我遇到以下情况 以下代码被写入我的页面 div Some text here which is not wrapped in tags p Some more text which is fine p p Blah blah another
  • jqgrid 在编辑框中选择不正确的下拉选项值

    我正在使用表单编辑 表单中有两个选择框 一个选择框是国家 地区 另一个选择框是州 州选择框取决于所选的国家 地区 并将动态填充 例如 Country 美国 期权价值 1 英国 期权价值 2 美国的状态 阿拉巴马州 选项值 1 加利福尼亚州
  • 如何处理 d3 中 Beeswarm 图中的碰撞?

    我一直在玩这个例子here https gf neocities org co2bs co2bee html一会儿 我想做的是突出显示图中的单个节点 圆圈 通过使用边框使其变大 稍后我也想在其中添加文本或字母 目前 我已经圈了Bhutan图
  • Google 文档 - 以编程方式将鼠标点击发送到大纲窗格中的项目

    在 Google 文档中 您可以打开大纲窗格并查看文档中的所有标题 您也可以单击标题 视图将滚动到标题 我的问题是如何使用 Chrome 扩展中的 JS 以编程方式模拟鼠标单击 以将视图滚动到所需的标题 我尝试了以下代码 但没有任何反应 u
  • 使用什么事件来在选择文本框中的值时显示警报消息

    我正在使用 jquery 的自动完成 api 来从数据库中获取名称 但是我想在从显示的文本框中选择名称时显示一条警报消息 我将显示一个图像以便更好地理解 当我输入 S 时 它将显示所有包含 S 的记录 所以问题是 如果我选择例如 Spars
  • 如何延迟 NavLink 的反应?

    Delay e gt e preventDefault setTimeout gt e unpreventDefault make this work 500 render
  • Angular - Safari 无法正确显示 DOM

    我是 Angular 的新手 使用 Angular 4 我尝试通过在关联的组件类文件中设置属性来更新特定元素 但是 除非我尝试强制重新绘制网页 通过调整窗口大小等 否则页面不会更新 我打开检查器 看到 DOM 已更改 但显示与元素检查器中的
  • Sequelize 4.3.2 n:m(多对多)关联:未处理的拒绝 SequelizeEagerLoadingError

    我有 3 个模型 用户 项目 UserProject module exports function sequelize DataTypes var User sequelize define User title DataTypes ST
  • 无法从 Twin.macro 中的 Prop 获取值

    您可以在这里查看我正在尝试执行的操作的示例 https codesandbox io s vibrant leaf qj8vz https codesandbox io s vibrant leaf qj8vz 注意 这个特定的例子使用双宏
  • 在js中检测浏览器的最佳方法

    JavaScript 中有很多浏览器检测方法 据我所知 使用navigator userAgent或检测特征 例如XMLHttpRequest 等等 谁能告诉我哪种方法最好 最有效 如果你真的需要知道什么browser他们正在使用 你主要需
  • 将 ESLint 与 Airbnb 样式和选项卡结合使用 (React.js)

    我正在开发一个 React js 应用程序 并且正在尝试检查我的代码 我将 ESLint 与 Airbnb 风格一起使用 但出现以下错误 src Test jsx 4 2 error Unexpected tab character no
  • 如何按值删除数组中的多个项目?

    我正在尝试做一个removeAll 函数 它将删除具有该特定值 而不是索引 的数组的所有元素 当我们对循环进行任何更改时 棘手的部分就出现了 索引往往会移动 使其很难像我们想要的那样工作 并且每次更改时都重新启动循环 这在大数组上效率非常低
  • Jquery获取每个div的子子div并将信息抓取到数组中

    我有一些看起来像这样的 html div div class sub main div div
  • 在部分渲染时执行 JavaScript

    我有一些 JavaScript 代码 我想在用户单击其文件夹之一后执行 它会触发 show 操作和 show js erb 从而呈 现部分内容 Show js erb 当用户单击其文件夹之一时触发 如下所示 body append 它成功注
  • 需要根据用户选择有条件地渲染具有 X 行数的部分

    我有一个反应组件 其中包含一个下拉列表 其中的选项包括none 1 5 and 13 根据用户选择的数字 我需要渲染一个部分 其中包括许多行 每个行都有字段名称和下拉列表 如果用户不选择任何一个 我需要整个附加配置部分消失 新部分中的每个下
  • 如何将命名空间与 TypeScript 外部模块一起使用?

    我有一些代码 基本类型 ts export namespace Living Things export class Animal move export class Plant photosynthesize dog ts import
  • 右列固定的 Div 表

    我最近接手了一个非营利网站作为一个项目 我正在使用一个现有的网站 所以我必须使用很多已经编程的东西 所以我所要做的就是创建设计 I made a diagram of basically what I can t figure out ho
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM

随机推荐