Promise的回调函数传入另一个Promise的疑惑?

发布于 2022-09-05 19:53:39 字数 914 浏览 24 评论 0

在阮一峰老师的《ES6标准入门》里面看到关于Promise的一个代码,让我很费解:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('fail')), 3000)
})
var p2 = new Promise(function (resolve, reject) {
    setTimeout(() => resolve(p1), 1000)
})
p2
.then(result => console.log(result))
.catch(error => console.log(error))

上述代码的输出结果是:Error: fail
而书上的表述是:

上面代码中,p1是一个Promise,3秒之后变为rejected。p2的状态在1秒之后改变,resolve方法返回的是p1。此时,由于p2返回的是另一个
Promise,所以后面的then语句都变成针对后者(p1)。又过了2秒,p1变为rejected,导致触发catch方法指定的回调函数。

这个就让我觉得很费解了。

  • 为什么p2后跟的then针对的是p1而不是p2本身呢?

  • p2中resolve(p1)这个到底发生了什么呢?为什么说“resolve方法返回的是p1”?resolve方法在此处不是应该是.then(result => console.log(result))吗?它返回undefined的呀?

  • 如果我就是想在控制台中打印出p1这个对象本身,即可以查看p1的属性等等,那么p2的then的回调函数代码应该怎么写呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

橘虞初梦 2022-09-12 19:53:39

首先,从简单的 Promise 理解开始。先别扯 Promise 嵌套的问题。因为最朴素的 Promise 概念你就弄错了。

var p = new Promise(function(resolve, reject) {
  resolve(1);
});

var cb = function(data) {
  console.log(data);
};

p.then(cb); // cb函数 和 上面的 resolve 不是一个东西!不是!

看起来 Promise 里的 resolve 方法就像是 then 方法传递过来的这个回掉函数?当然不是!resolve 是指用一个值来 完成 这个 promise,只有 promise resolve了,then方法注册的回掉才会被执行。同理,即使没人关心你这个 promise 是否会被 resolve,没有人用 then 注册回掉函数,resolve 照样可以正常执行。

为什么p2后跟的then针对的是p1而不是p2本身呢?

为什么?标准就是这样规定的啊!

标准规定,如果你用普通对象来 resolve 一个 promise,这个promise就立马拿着这个值然后变成 resolved 状态,如果你用一个 thenable 的对象,就是一个promise对象 来 resolve 另一个 promise,这个 promise 就会自动关联起来!

var p1 = new Promise(function(resolve) {
  setTimeout(function(){
    resolve(1);
  }, 1000);
});

var p2 = new Promise(function(resolve, reject) {
  resolve(p1);
  // 等价于
  p1.then(resolve).catch(reject);
});
// 标准就是这样规定的,这才是 promise 的价值所在,否则和普通的callback有什么区别?

要在 p2.then 里拿到 p1 ?

那你别用一个 promise 对象作为值来 resolve p2 啊!

话说你又是为什么要在 then 里拿到 p1呢?拿到p1你又能干什么的?还不是调用.then 么?
话说你又是为什么要在 then 里拿到 p1呢?拿到p1你又能干什么的?还不是调用.then 么?
话说你又是为什么要在 then 里拿到 p1呢?拿到p1你又能干什么的?还不是调用.then 么?

不存在这种需求的,没道理要这样作,如果要,那你这样啊:

resolve([p1])

p2.then(([p1]) => {
// p1
})

妄想挽回 2022-09-12 19:53:39

泻药。
你没有正确理解promise中的resolve,其作用是完成promise并返回其参数值。
这里p2就是1s后resolve(p1),由于其返回值p1是promise对象,则不会进入then,会继续执行这个promise。
第三个问题感觉没有什么方法,then中是要等p1中完成才能执行。

晨光如昨 2022-09-12 19:53:39

参考 MDN 上的 PromisePromise.resolve(),有如下一段话

返回一个状态由给定value决定的Promise对象。如果该值是一个Promise对象,则直接返回该对象;如果该值是thenable(即,带有then方法的对象),返回的Promise对象的最终状态由then方法执行决定;否则的话(该value为空,基本类型或者不带then方法的对象),返回的Promise对象状态为fulfilled,并且将该value传递给对应的then方法。通常而言,如果你不知道一个值是否是Promise对象,使用Promise.resolve(value) 来返回一个Promise对象,这样就能将该value以Promise对象形式使用。

虽然这是介绍的 Promise.resolve() 静态方法,而且文档中也没提到对 new Promise() executor 的 resolve() 适应,但实际效果表示二者处理方式是一样的。

2022-09-12 19:53:39

resolve 会对 thenable 的对象剥开处理的。

所以你想返回 p1 的话可以对其包一层对象,比如 resolve({p1})

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文