• JavaScript 在 Promise.then 方法里返回新的 Promise


    看一个实际的例子:

    loadScript("/article/promise-chaining/one.js")
      .then(function(script) {
        return loadScript("/article/promise-chaining/two.js");
      })
      .then(function(script) {
        return loadScript("/article/promise-chaining/three.js");
      })
      .then(function(script) {
        // use functions declared in scripts
        // to show that they indeed loaded
        one();
        two();
        three();
      });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    按照先后顺序,依次加载 one.js, two.js, three.js

    当然也可以使用箭头函数的语法:

    loadScript("/article/promise-chaining/one.js")
      .then(script => loadScript("/article/promise-chaining/two.js"))
      .then(script => loadScript("/article/promise-chaining/three.js"))
      .then(script => {
        // scripts are loaded, we can use functions declared there
        one();
        two();
        three();
      });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这里每个 loadScript 调用,都会返回一个 promise,这个新的 promise,在其被 resolve 时,会触发下一个 .then 的执行。

    于是它开始加载下一个脚本。 所以脚本一个接一个地加载。

    我们可以向链中添加更多异步操作。 请注意,代码仍然是 flat 的——它向下增长,而不是向右增长。

    这种方式没有 pyramid of doom 的迹象。

    虽然我们可以在 then 后面直接调用 loadScript:

    loadScript("/article/promise-chaining/one.js").then(script1 => {
      loadScript("/article/promise-chaining/two.js").then(script2 => {
        loadScript("/article/promise-chaining/three.js").then(script3 => {
          // this function has access to variables script1, script2 and script3
          one();
          two();
          three();
        });
      });
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    此代码的作用相同:依次加载 3 个脚本。 但它 向右增长, 所以本质上仍然有回调地狱的问题。

    Thenables 对象

    准确地说,then 处理程序可能返回的不完全是一个 Promise,而是一个所谓的 thenable 对象——一个具有 .then 方法的任意 JavaScript 对象。 它将被视为与 Promise 相同的方式被处理。

    这个想法是第 3 方库可以实现自己的 promise-compatible 对象。 它们可以有一组扩展的方法,但也可以与原生 Promise 兼容,因为它们实现了 .then。

    看一个例子:

    class Thenable {
      constructor(num) {
        this.num = num;
      }
      then(resolve, reject) {
        alert(resolve); // function() { native code }
        // resolve with this.num*2 after the 1 second
        setTimeout(() => resolve(this.num * 2), 1000); // (**)
      }
    }
    
    new Promise(resolve => resolve(1))
      .then(result => {
        return new Thenable(result); // (*)
      })
      .then(alert); // shows 2 after 1000ms
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    单步调试:

    1. 14 行 new Promise 内部的 executor 得到执行,立即 resolve,抛出 result 1

    1. 这会导致代码第 15 行 then 里的函数立即被调用,输入参数为 1,构造一个新的 Thenable 对象。

    JavaScript 在第 16 行中检查 .then 处理程序返回的对象:如果它有一个名为 then 的可调用方法,那么它调用该 then 方法,并提供本地函数 resolve、reject 作为参数(类似于执行程序)并等待其中一个被调用。 在上面的示例中,resolve(2) 在 1 秒 (**) 后被调用。然后将结果进一步向下传递。

    因此,下图第 16 行代码单步调试之后,会自动进入代码第 8 行。

    1. 打印出 resolve 原生函数的 native code 字符串。

    1. 代码第 10 行的 resolve,会触发第 18 行第二个 then 方法:

  • 相关阅读:
    There are test failures.【非常详细,已解决】
    MATLAB中左边的大括号最后一行为什么会留很大的空白——解决
    jenkins升级版本遇到的问题
    Android 深入理解 Service 的启动和绑定
    Golang 继承
    软件测试———linux
    redis 多租户隔离 ACL 权限控制(redis-cli / nodejs的ioredis )
    这些数据泄露方式,80%的企业不易发现
    【C语言学习笔记---内存函数】
    数据结构与算法概览图
  • 原文地址:https://blog.csdn.net/i042416/article/details/126306465