【问题标题】:What is the use of ES6 Promise then() fulfillment handler returning a value?ES6 Promise then() 实现处理程序返回值有什么用?
【发布时间】:2019-12-26 12:54:31
【问题描述】:

据说inside a .then() fulfillment handler, if a value v1 (a non promise object) is returned, then the promise as returned by then() will be a resolved promise, with the resolved value v1

但是这个功能有什么用呢?如果我们立即解决这个承诺,我们还不如直接在这个 then() 实现处理程序中编写代码。

例子:

myPromise.then(function(someV) {
  // ...
  return v1;
}).then(function(v) {
  // some code

也就是说,我们不妨将// some code 移动到第一个履行处理程序中。

(我认为通常的用例是返回 new Promise() 以便我们可以链接承诺。)

【问题讨论】:

  • 你能引用具体的句子吗?它说“then() 返回的承诺将是一个已解决的承诺”?我在该 MDN 页面上只能找到诸如“then 返回的承诺得到解决”之类的提及(没有直接的时间限定)。返回的承诺始终处于未决状态。
  • @Bergi 它是该列表中的第一项:“返回一个值,然后返回的承诺以返回的值作为其值来解决。”
  • 我想我误解了你的问题。您是在询问将代码移动到 next then 处理程序中,而不是将其移动到 then 处理程序下方(和外部),以防承诺被同步解决(它永远不会)。
  • 您可能不会编写这样的代码,即您总是将“// some code”移动到第一个处理程序中。但是一个承诺链最终必须返回一个非承诺值是相当明显的,所以我有点迷失在你迷失在这里的地方。

标签: javascript es6-promise


【解决方案1】:

这是一个不错的问题。在其他“一元结构”中,有两个函数用于此(一个用于映射,另一个用于映射一个承诺),但在 2013 年的某个时候,它决定不在 JavaScript 中做同样的事情并允许返回一个值。

这对于使用 Promise 链接操作是有意义的, 不执行异步操作。例如:

fetch('./foo').then(x => x.json()).then(JSON.parse);

最后JSON.parse 部分与promise 或异步操作无关。

【讨论】:

  • 最后一个then将解析已经被x.json()解析的Javascript对象?
  • x.json() 返回 JSON 字符串,JSON.parse 解析字符串?我想有时你会返回一些值并使其成为一个已解决的承诺是有道理的。在您的示例中,您可以将其设为 fetch('./foo').then(x => JSON.parse(x.json())) 吗?虽然,它仍然在没有进一步链接的情况下返回一个值
【解决方案2】:

在许多情况下,第一个 Promise 处理程序返回一个纯值,但不能轻易地与链中的第二个 Promise 处理程序合并:

  • 中间promise是函数的返回值:

    function fn() {
      return myPromise.then(… => { …; return v1; });
    }
    fn().then(…)
    
  • 除了返回值之外,第一个处理程序也可能抛出异常,在这种情况下,第二个处理程序不应该运行,而是拒绝处理程序:

    myPromise.then(… => {
      if (…) throw new Error(…);
      else return v1;
    }).then(…, err => …);
    
  • 第一个处理程序也可能在其他执行路径上返回一个承诺,这需要由第二个处理程序等待:

    myPromise.then(… => {
      if (…) return fetchSomethingByPromise();
      else return v1;
    }).then(…);
    
  • 除了第一个处理程序之外还有一个拒绝处理程序,第二个处理程序也应该得到它的结果:

    myPromise.then(… => v1, err => v2).then(…);
    

在所有这些情况下,then 函数都需要处理普通值。当然,它们总是可以被包裹在Promise.resolve(v1) 中,但我们决定不这样做。 then 需要处理原始值还有一个原因:一个 void 处理程序(例如在链的末尾)返回 undefined,而 then 需要适当地处理它。

【讨论】:

    【解决方案3】:

    我想我对 promises 了解得更多,以便对此有所了解:

    无论履行处理程序返回什么,原始值,不是 thenables 的对象,thenables,真正的 Promise,此值将始终解析 p,或制成一个 Promise 以便它解析 p,其中 p.then() 返回什么。

    我相信这在 Promise 社区中被称为解包。

    所以如果返回一个原始值或一个不可用的对象:

    该值将用于解析p,或者将其制成Promise.resolve(v)立即解析,即立即解析p

    如果它是一个 thenable 或一个真正的 promise 的对象:

    可以这样称呼:

    obj.then(resolveP) 其中resolveP 是可以解析p 的函数。

    那么 thenable 和 real promise 都可以解析p

    在 Promise 社区中,似乎即使是原始值或不可 thenable 的对象,也会被制成 Promise,以便未来的操作更加一致:对 Promise 的操作。

    你包裹和包裹都没关系,因为它无论如何都会解开和解开。 (当内部承诺解决时,它会将展开传播到外部包装,直到它无法继续。)

    感觉就像 Promise 是更高级别的对象,从现在开始,我们只会使用它们。 (当我们处理promise和普通值时,一切都会被转换成promise(通过使用Promise.resolve(value)并处理)。

    【讨论】:

      猜你喜欢
      • 2020-04-16
      • 1970-01-01
      • 1970-01-01
      • 2022-12-28
      • 2016-09-30
      • 2018-05-09
      相关资源
      最近更新 更多