ES6 Promise 返回值的执行顺序

2024-05-05

尝试了解 ES6 Promise 的执行顺序,我注意到链式处理程序的执行顺序受到前一个处理程序返回值还是 Promise 的影响。

Example

let a = Promise.resolve();
a.then(v => Promise.resolve("A")).then(v => console.log(v));
a.then(v => "B").then(v => console.log(v));

直接在 Chrome (v 61) 控制台中运行时的输出:

B
A

然而,当点击Run code snippet按钮,我会收到订单A B反而。

上面的例子的执行顺序是ES6中定义的,还是由实现决定?

如果定义了,正确的输出应该是什么?


Promise.resolve指定返回已解决的承诺(令人兴奋,对吧?25.4.4.5、25.4.1.5、25.4.1.3。)。a.then()因此立即将作业加入队列(25.4.5.3.1 https://tc39.github.io/ecma262/#sec-performpromisethen,每次都执行步骤 8)。.then()根据此规范,永远不会返回已履行的承诺(对于一些有趣的事情,请尝试Promise.resolve().then()在您的 Chrome 控制台中¶

让我们为承诺命名a.then(v => Promise.resolve("A"))及其一些相关的规格状态p1². This .then()排队要调用的作业(25.4.2.1 https://tc39.github.io/ecma262/#sec-promisereactionjob) a.then(v => Promise.resolve("A"))如上所述。

首先.then(v => console.log(v))附加对应于的承诺反应v => console.log(v)₁ 待处理承诺的履行反应列表p1 (still 25.4.5.3.1 https://tc39.github.io/ecma262/#sec-performpromisethen).

  • 现在队列是:

    1. 完成反应工作v => Promise.resolve("A")
  • p1现在有v => console.log(v)₁ 在其履行反应列表中

承诺a.then(v => "B") can be p2。目前它的工作方式相同。

  • 现在队列是:

    1. 完成反应工作v => Promise.resolve("A")
    2. 完成反应工作v => "B"
  • p1 has v => console.log(v)₁ 在其履行反应列表中

  • p2现在有v => console.log(v)2 在其履行反应列表中

我们已经到了脚本的结尾。

第一份工作时,对应v => Promise.resolve("A"),出列并调用(再次25.4.2.1 https://tc39.github.io/ecma262/#sec-promisereactionjob), a then在结果中发现(这是重要的部分),导致另一个作业排队(25.4.1.3.2 https://tc39.github.io/ecma262/#sec-promise-resolve-functions,步骤 12),无论该结果的承诺状态如何。

  • 现在队列是:

    1. 完成反应工作v => "B"
    2. call Promise.resolve("A").then with p1的[[解决]]和[[拒绝]]
  • p1 has v => console.log(v)₁ 在其履行反应列表中

  • p2 has v => console.log(v)2 在其履行反应列表中

下一个作业将出列并被调用。一个可调用的then is not根据结果​​发现,所以p2立即满足(25.4.1.3.2 https://tc39.github.io/ecma262/#sec-promise-resolve-functions再次执行步骤 11a) 并为每个任务排队p2的满足反应。

  • 现在队列如下:

    1. call Promise.resolve("A").then with p1的[[解决]]和[[拒绝]]
    2. 打电话(通过25.4.2.1 https://tc39.github.io/ecma262/#sec-promisereactionjob) v => console.log(v)
  • p1 has v => console.log(v)₁ 在其履行反应列表中

我将在这里停止这一级别的解释,因为Promise.resolve("A").then开始整个then再次序列。不过,您可以看到这是怎么回事:作业队列是一个queue,并且将产生输出的一个函数已在队列中,而另一个尚未添加。队列中的那个将首先运行。

正确的输出是 B 后跟 A。

那么,既然这样,为什么 Chrome 中的答案在一个页面中是错误的呢?这不是一些 Stack Overflow 片段填充程序;您可以使用一些 HTML 本身或在 Node.js 中重现它。我的猜测是,这是一个违反规范的优化。

'use strict';

class Foo extends Promise {}

let a = Promise.resolve();
a.then(v => Foo.resolve("A")).then(v => console.log(v));
a.then(v => "B").then(v => console.log(v));

的替代定义thenable带着这个乐趣node --allow_natives_syntax script!

'use strict';

const thenable = p => ({ then: p.then.bind(p) });
//const thenable = p => p;

let a = Promise.resolve();
a.then(v => {
    %EnqueueMicrotask(() => {
        %EnqueueMicrotask(() => {
            console.log("A should not have been logged yet");
        });
    });

    return thenable(Promise.resolve("A"));
}).then(v => console.log(v));
a.then(v => "B").then(v => console.log(v));

¹ For posterity: it’s a resolved promise in Chrome 61.0.3163.100.
² That’s less specific than the spec, but this is an answer trying to describe the spec and not a spec. With any luck, it’s even right, too.

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

ES6 Promise 返回值的执行顺序 的相关文章

随机推荐

  • Prisma 1 到 2 迁移问题:P4001 内省数据库为空

    因此 我一直在尝试在现有数据库上运行内省过程 如下所示 npx prisma introspect 并收到以下错误跟踪 0 info it worked if it ends with ok 1 verbose cli C Program
  • 无法在 Android MediaRecorder 中设置手动视频大小

    我正在Android中使用MediaRecorder来录制视频 我当前的参数是 mMediaRecorder setAudioSource MediaRecorder AudioSource DEFAULT mMediaRecorder s
  • 在 unnest_wider 之后命名提升向量中的列

    在使用 tidyr 1 0 的一些新功能时 我遇到了一些令人头疼的问题 我用过boxplot stats获取我想用来绘制的箱线图值向量 我已经成功地完成了此操作 但我相信有更好的方法来命名新的未嵌套向量的列 这是当前设置 library t
  • 重复符号_OBJC_CLASS_$_LoginController

    我知道这个问题以前已经被问过很多次了 但到目前为止还没有解决我的问题 我知道当您在项目中获得文件的多个副本时 会发生此错误 我尝试清理构建 删除任何登录控制器 m文件输入编译源然后构建 很好 没有错误 当我在编译源中添加 LoginCont
  • 控制台界面教程和提示 (pdcurses)

    我正在寻找有关使用 PDCurses 库的教程 不幸的是 只有文本文档 这更像是函数参考 pdcurses 是否与 ncurses 足够相似以使用 ncurses 教程 关于制作控制台 UI 的任何提示 附言 PDCurses mingw3
  • Vagrant - Homestead 设置多个站点

    我已经使用 homestead yaml 映射了文件夹等 ip 192 168 10 10 folders map Users User Desktop folder Homestead First to home vagrant Firs
  • 使用EF Core调用存储过程并关闭连接

    我有一个使用 EF Core 的 ASP NET Core 2 2 应用程序 我有一个服务类 通常使用DbContext用于任何 CRUD 操作 然而 在其中一种方法中 Assign下面的方法 我需要使用存储过程 所以我使用以下代码 注意D
  • 在重复键上仅更新 Null 或空值

    我有一个 mysql 查询来合并主键 IMO 上的两个表 查询工作正常 但我遇到的问题是在重复键更新时 我只想更新 wp second 表的那些没有值的字段 简而言之 在重复键上 wp second 值仅应在 null 或空时更新 这是我到
  • polyfit numpy 的反向输出

    我使用了 numpy 的 polyfit 并获得了两个数组 x 和 y 的非常好的拟合 使用七阶多项式 我的关系是这样的 y x p 0 x 7 p 1 x 6 p 2 x 5 p 3 x 4 p 4 x 3 p 5 x 2 p 6 x 1
  • UCM 中的复合基线是什么以及何时使用它?

    UCM 中的综合基线是什么 什么时候会用到 主要是当我们有多个组件的时候才会使用它吗 关于 复合基线 的参考文献是 在 UCM 中使用复合基线的最佳实践 http www ibm com developerworks rational li
  • 在 pandas dataframe python 列中搜索单词

    我有两个文本列 我想查找一列中的单词是否存在于另一列中 我编写了下面的代码 它运行得很好 但它会检测字符串中的任何位置是否存在单词 例如 它将在 ham 中查找 ha 我想改用正则表达式 但我被困住了 我遇到了这个post https st
  • bash 用变量值替换字符串中的变量名

    这有点奇怪 我有以下字符串 我有一个名为 REDIRECT 的变量设置为 https working MYDOMAIN blah blah 我需要将 MYDOMAIN 替换为分配给 MYDOMAIN 的变量的实际值 不确定 bash 还是
  • Java机器学习库可以商用吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道我可以将其用于商业产品的优秀 Java 机器学习库吗 不幸的是 Weka 和 Rapidmin
  • 验证远程图像实际上是 ruby​​ 中的图像文件?

    我试图弄清楚如何验证我输入载波的内容实际上是图像 我获取图像网址的来源并没有返回所有实时网址 有些图像已不复存在 不幸的是 它并没有真正返回正确的状态代码或任何内容 因为我正在使用一些代码来检查远程文件是否存在并且它通过了该检查 因此 现在
  • 使用 Apache Batik 将 SVG 图像转换为 JPEG 图像

    我正在尝试将 SVG 图像转换为 JPEG 如下所示https xmlgraphics apache org batik using transcoder html createImage https xmlgraphics apache
  • res.redirect 不会重定向 Node/Express.js

    我正在为我的 web 应用程序使用 Express 并检查会话中是否存在某些值 将用户重定向到 Instagram 登录页面 但在控制台中我不断收到 302 代码 并且浏览器不会重定向用户 这是我的代码 我正在使用 Ajax 发送我的请求
  • 如何将子记录添加到现有父记录中?

    我一直在 Google 和 Stack Overflow 上搜索有关这个主题的某种提示 但信息充其量是分散的 我正在尝试创建一个新的子记录 Comment 并将其保存到现有的父记录 Post 我使用的是 Ember Model 而不是 Em
  • 使用 JSON 将 iTunes 中的图像解析为 tableviewcontroller

    我正在尝试从中解析数据数据源 http ax itunes apple com WebObjects MZStoreServices woa ws RSS topsongs limit 30 json 标题已正确解析并显示 但解析图像时出现
  • Wordpress 数组显示特定类别的帖子并显示帖子摘录和功能

    大家好 正在寻找 WordPress 帮助 我需要放置一个简单的查询 数组来显示来自某只猫的帖子 例如 新闻 其中将包含帖子特色图像 有人可以帮忙吗 Gary Try this a href title a
  • ES6 Promise 返回值的执行顺序

    尝试了解 ES6 Promise 的执行顺序 我注意到链式处理程序的执行顺序受到前一个处理程序返回值还是 Promise 的影响 Example let a Promise resolve a then v gt Promise resol