【Promise】由thenable引发的一系列问题

群友偶然在群里问起的一道关于Promise的题,疑惑于为什么打印结果竟然是两个then一个data,当我以为能像往常一样轻松答出,没想到在我一步步求证的过程中,让我之前很多“想当然”的细节被否决,而网上关于thenable的用法介绍又非常少,我只能对自己对可能出错的细节,列出所有可能进行一个个求证,奋战数日终于攻克,在此记录一番

const thenable = {
    then(resolve, reject) {
      console.log("then");
      resolve("data");
      //reject("reason")
    },
  };

Promise.resolve(thenable).then(
    (res) => console.log(res),
    (err) => console.log(err)
)


 console.log(Promise.resolve(thenable));


一、thenable基本作用

网上查得到的对thenable的介绍:

thenable对象指的是具有then方法的对象。Promise.resolve方法会将这个对象转为Promise对象,然后立即执行thenable对象的then方法。

二、一些细节上的推敲

1.立即执行?

const thenable = {
    then(resolve, reject) {
      console.log("then");
      resolve("data");
      //reject("reason")
    },
  };

Promise.resolve(thenable).then(
    (res) => console.log(res),
    (err) => console.log(err)
)


 console.log(Promise.resolve(thenable));
 console.log('aaa'); //新增打印

我们对“立即执行”进行求证,把这串代码稍加修改,打印结果如下
在这里插入图片描述
aaa竟然在then和data之前打印?!说明thenable里面的then方法,其实也是异步代码
而网上资料所说的thenable立即执行里面的then方法,准确的说是在then链式调用的时候,在下一个then方法调用之前,会立即执行thenable里面的then方法,返回由thenable转为的新promise

2.Promise.resolve(thenable).then到底做了什么

一开始,我以为,这是一个then方法,本应该加入到微任务队列中,但是因为thenable返回的新promise是pending状态,所以不执行。
但是,看这段代码

const thenable = {
    then(resolve, reject) {
      console.log("then");
      resolve("data");
      //reject("reason")
    },
  };

Promise.resolve(thenable).then(
    (res) => console.log(res),
    (err) => console.log(err)
)

打印结果
在这里插入图片描述
如果第9行真如上面所猜想一样,因为promise状态是pending所以不执行,那控制台根本就不会有输出!

并且发现,每新增一个Promise.resolve(thenable),就会多打印一个then,说明thenable对象里面的then方法就被调用了一次!
在这里插入图片描述
所以我们可以推测得知,在第9行,Promise.resolve(thenable).then()其实做了两件事:

  1. Promise.resolve(thenable)调用了thenable里面的then方法
  2. 将这个新产生的Promise所对应的.then()方法,加入到微任务队列中

回顾

最后再来回顾这道题,其实现在看脉络就很清晰了。
在这里插入图片描述
其实也可以直接将Promise.resolve(thenable)改造为 new Promise(resolve => resolve(thenable) )

在这里插入图片描述

  1. 碰到一个对象声明,继续往下执行
  2. 第23行开始,resolve的是一个thenable对象,将thenable对象的执行加入微任务队列, 记作微1。
  3. 第30行,打印,为主线程任务,所以在控制台会先打印出这个Promise的状态:Pending。32行resolve的同样是一个thenable对象,将thenable对象的执行加入微任务队列, 记作微2。
  4. 此时主线程清空,开始执行微任务
  5. 微1执行,打印第一个then,resolve(‘data’)调用,此时将23行的promise状态改位resolved,将第26行对应的then()方法成功回调加入微任务队列,记为微3
  6. 微2执行,打印第二个then,resolve(‘data’)调用,但此时,31行对应的新promise没有对应的.then()方法,所以微2执行结束
  7. 微3执行,打印data,此时微任务也全部清空完成,程序运行结束

完结撒花~~~ Promise也不过如此嘛

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值