草庐IT

javascript - 为什么带有 'await'的这行代码会触发微任务队列处理呢?

coder 2024-05-14 原文

以下引述是我理解微任务队列处理的主要引用资料:

Microtasks (which promises use) are processed when the JS stack empties.

- Jake Archibald

这对我来说没有意义。

One go-around of the event loop will have exactly one task being processed from the macrotask queue (this queue is simply called the task queue in the WHATWG specification). After this macrotask has finished, all available microtasks will be processed, namely within the same go-around cycle.

- Stack Overflow

现在,关于以下代码段中的第 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()

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

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

然后是紧接着的下一步。

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

调用堆栈是否在这些步骤之间清除了[幕后]^?

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

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

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

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

最佳答案

"Microtasks (which promises use) are processed when the JS stack empties." -Jake Archibald (doesn't make sense to me)

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

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

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

bar();

当我们命中第一个调试器语句时,脚本仍在执行,bar 也是,foo 也是。由于存在父子关系,堆栈为 script > bar > foo。当我们点击第二个调试器语句时,foo 已完成执行,因此它不再位于堆栈中。堆栈是 script > bar

当堆栈变空时,微任务队列会一直处理到它为空。

"One go-around of the event loop will have exactly one task being processed from the macrotask queue (this queue is simply called the task queue in the WHATWG specification). After this macrotask has finished, all available microtasks will be processed, namely within the same go-around cycle." - stackoverflow

编辑:我一直把上面的“macrotask”读成“microtask”。浏览器中实际上并没有宏任务队列这样的东西,它只是一个任务队列。

虽然在处理任务后确实有一个微任务处理点,​​但它只是真正在那里处理规范,将任务排队到队列微任务,而不需要先调用JS。大多数时候,微任务队列在 JS 堆栈清空时清空。

From stepping through this snippet w/ debugger, the execution stack does not appear empty when these .then( callback ) microtasks are processed/executed.

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

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

Are regular functions like f2() considered a task

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

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

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

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

one();

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

关于javascript - 为什么带有 'await'的这行代码会触发微任务队列处理呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56851983/

有关javascript - 为什么带有 'await'的这行代码会触发微任务队列处理呢?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  4. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  5. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  6. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  7. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  8. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  9. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  10. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

随机推荐