理解 JS 承诺 [英] Understanding JS Promises

查看:15
本文介绍了理解 JS 承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想更深入地了解 Promises 在内部是如何工作的.因此我有一些示例代码:

I would like to get a deeper understanding of how Promises work internally. Therefore I have some sample code:

var p1 = new Promise(
  function(resolve, reject) {
    window.setTimeout(
      function() {
        resolve('res called')
      }, 2000);
  });


var p2 = new Promise(
  function(resolve, reject) {
    window.setTimeout(
      function() {
        resolve('res called')
      }, 2000);
  });


function chainPromises() {
  return p1.then(function(val) {
    console.log("p1");
    return p2.then(function(val) {
      console.log("p2");
      return val;
    });
  });
}

chainPromises().then(function(val) {
  console.log(val);
});

这里有一个 链接 来执行此代码.

Here a link to execute this code.

如您所料,首先解析 p1,然后解析 p2,最后打印解析值.

As you would predict, first p1 is resolved, afterwards p2 and in the end the final then prints the resolv value.

但 API 参考声明如下:

But the API ref states the following:

"then" 返回一个新的promise,相当于你从中返回的值通过 Promise.resolve 传递后的 onFulfilled/onRejected

"then" returns a new promise equivalent to the value you return from onFulfilled/onRejected after being passed through Promise.resolve

所以知道then"函数的确切执行时间会很有趣?因为代码中最后的then"链接到了chainPromises(),我首先想到的是它会在函数 chainPromises() 返回一些东西后执行(在这种情况下是另一个承诺).

So it would be interesting to know WHEN exactly the "then" function is executed? Because the final "then" in the code is chained to the chainPromises(), I first thought that it would execute after the function chainPromises() returns something (in this case another promise).

如果是这种情况,最终then"函数的val"将是返回的promise.但是相反,最后的then"一直等到第一个then"中返回的所有承诺都已解决.这绝对是有道理的,因为通过这种方式,then"函数可以堆叠,但是由于 API 规范,我真的不明白这是如何完成的.并没有真正涵盖then"返回的内容以及then"函数的执行时间.

If this would have been the case the "val" of the final "then" function would be the returned promise. But instead, the final "then" waits until all promises inside the first "then" which are returned have been resolved. This absolutely makes sense because in this way, the "then" functions can be stacked, but I do not really get how this is done, since the API spec. does not really cover what "then" returns and when the "then" functions is executed.

或者换句话说,为什么最终的then"函数要等到所有的 Promises 在 chainPromises() 函数内被解析,而不是像 API 文档所说的那样等待第一个返回的对象.

Or in other words, why does the final "then" function wait until all the Promises are resolved inside the chainPromises() function instead of just waiting for the first returned object as the API doc says.

我希望我能说清楚我的意思.. :)

I hope I could make clear what I mean.. :)

推荐答案

关于 Promise 解决方案

您在这里看到的事情称为递归thenable resolution.Promises/A+ 规范中的 promise 解析过程包含以下子句:

About Promise resolution

The thing you're witnessing here is called recursive thenable resolution. The promise resolution process in the Promises/A+ specification contains the following clause:

onFulfilled 或 onRejected 返回值 x,运行 Promise 解析过程 [[Resolve]](promise2, x)

onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x)

ES6 承诺规范(promises unwrapping)包含一个类似的条款.

The ES6 promise specification (promises unwrapping) contains a similar clause.

这要求当 resolve 操作发生时:在 promise 构造函数中,通过调用 Promise.resolve 或在您的情况下在 then> 链接一个承诺实现必须递归地解包返回的值,如果它是一个承诺.

This mandates that when a resolve operation occurs: either in the promise constructor, by calling Promise.resolve or in your case in a then chain a promise implementation must recursively unwrap the returned value if it is a promise.

这意味着如果 onFulfilled(then)返回一个值,尝试自己解析"promise 值,从而递归地等待整个链.

This means that if onFulfilled (the then) returns a value, try to "resolve" the promise value yourself thus recursively waiting for the entire chain.

这意味着:

promiseReturning().then(function(){
    alert(1);
    return foo(); // foo returns a promise
}).then(function(){
    alert(2); // will only run after the ENTIRE chain of `foo` resolved
              // if foo OR ANY PART OF THE CHAIN rejects and it is not handled this 
              // will not run
});

例如:

promiseReturning().then(function(){
    alert(1);
    return Promise.resolve().then(function(){ throw Error(); });
}).then(function(){
    alert("This will never run");
});

然后:

promiseReturning().then(function(){
    alert(1);
    return Promise.resolve().then(function(){ return delay(2000); });
}).then(function(){
    alert("This will only run after 2000 ms");
});

这是个好主意吗?

在 promises 规范过程中,这一直是一个争论不休的话题,第二个链方法没有表现出这种行为,但已经讨论过但决定反对(在 Chrome 中仍然可用,但很快就会被删除).您可以在在此讨论主题中了解整个辩论.这种行为是出于务实的原因,因此您不必手动执行此操作.

Is it a good idea?

It's been the topic of much debate in the promises specification process a second chain method that does not exhibit this behavior was discussed but decided against (still available in Chrome, but will be removed soon). You can read about the whole debate in this esdiscuss thread. This behavior is for pragmatic reasons so you wouldn't have to manually do it.

值得一提的是,其他语言没有这样做,Scala 中的 futures 或 C# 中的任务都没有这个属性.例如,在 C# 中,您必须在任务上调用 Task.Unwrap 以等待其链解析.

It's worth mentioning that other languages do not do this, neither futures in Scala or tasks in C# have this property. For example in C# you'd have to call Task.Unwrap on a task in order to wait for its chain to resolve.

这篇关于理解 JS 承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆