乐趣区

关于前端:JavaScript-在-Promisethen-方法里返回新的-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();});

依照先后顺序,顺次加载 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();});

这里每个 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();});
  });
});

此代码的作用雷同:顺次加载 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. 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 办法:
退出移动版