关于《我用散装promise写了一个倒计时功能引发的后续灾难》这件事

本文通过一个使用Promise实现的倒计时功能,探讨了Promise决议的问题,包括resolve参数为value、promise和thenable时的不同情况。在resolve参数为value时,决议的值就是value;为promise时,状态会跟随返回的Promise状态;为thenable时,Promise会转换thenable对象并执行其then方法。最后,作者预告将进一步研究PromiseA+规范的细则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上代码为敬

function TimeCD(times,delay){

    //初始化参数
    this._init = ()=>{
        clearTimeout(this.timer)      
        this.times = times      
        this.timer = null       
        this.init = null
    }
    this._init()

    // 开始倒计时
    TimeCD.prototype.start = (operation)=>{
        if(!this.init){
            this.init = true
            eval(operation)
        }
        return new Promise((resolve,reject)=>{
            try {
                if(this.times>0){   
                    --this.times
                    this.timer = setTimeout(()=>{
                        eval(operation)
                        resolve(this.start(operation))
                    },delay)
                }else{
                    this._init()
                    resolve(true)                   
                }
            } catch (error) {
                reject(error)
            }
         })
    }

    // 结束倒计时
    TimeCD.prototype.end = (operation)=>{
        eval(operation)
    }

    // 停止倒计时
    TimeCD.prototype.stop = ()=>{
        this._init()
    } 
}

const test =new TimeCD(3,1000)

test.start("console.log('倒计时开始'+ this.times)").then(res=>{
    test.end("console.log('倒计时结束')")
})

控制台打印结果见图
在这里插入图片描述


这里用到了promise来阻塞end方法的执行。还有个小芝士promise存在嵌套的话,最里面的promisethen方法在外部是最先调用的哈(具体看下面解释)。


代码看完了,然后我们开始聊一聊promise决议的问题

resolve(value),其中value参数的值有三种,分别是

  • value(value是不具有then方法的对象或者根本不是个对象)
  • promise
  • thenable

1. resolve参数为value

返回一个新的promise对象,promise的状态就是 fulfilled

用人话说就是promise决议的值就是value,在then方法中可以获取到value


2. resolve参数为 promise

const p1 = new Promise((res,rej)=>{
    res(true)
})

const p2 = new Promise((res,rej)=>{
    res(p1)
})

const p3 = new Promise((res,rej)=>{
    res(p2)
})

直接看例子 p3 resolve p2,p2 resolve p1,p1 resolve 一个 value,再看看输出结果
在这里插入图片描述
1)其实是这么一个流程滴!

  • P3 在 resolve的时候 发现 value和值居然是一个promise实例,于是 P3会返回P2实例,并且等待P2状态改变且传递给P3
  • 但是P2在resolve的时候 value的值居然也是一个promise,这可真是雀食了,于是 P2 也只能返回 P1实例,等待P1的状态发生改变
  • P1在resolve的时候,发现resolve的值是一个原始数据,于是P1的状态直接变成了fulfilled,P1将自己的状态传递给P2,P2再将状态传递给P3。于是P3自己的状态已经 改变了。

2)没懂的话别急,再忍耐一下,我还有个栗子
在这里插入图片描述

//3秒之后 决议失败
const p1 = new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('fail')), 3000)
})

//1秒钟后决议成功
const p2 = new Promise(function (resolve, reject) {
    setTimeout(() => resolve(p1), 1000)
})

// 
p2.then(result => console.log(result))
.catch(error => console.log(error))

p2的状态在 1 秒之后改变,resolve方法返回的是p1。由于p2返回的是另一个 Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态。所以,后面的then语句都变成针对后者(p1),导致触发catch方法指定的回调函数。
这里的参考文章,大噶有空可以去康康

总结:当resolve的参数是promise的时候,会返回这个promise实例,并且状态会跟随返回来的promise的状态


3.resolve参数为thenable

请你们吃个栗子先

let thenable = {
    then: function(resolve, reject) {
      resolve('参数类型是thenable');
    }
  };
  let p1 = new Promise((res,rej)=>{
      res(thenable)
  })
  p1.then((res)=> {
    console.log(res);     // 参数类型是thenable
  });

p1的resolve里面是一个具有then方法的对象,Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
值得注意的是,这里只有当 then方法执行后,p1的状态才会发生改变。随后调用then的回调函数


通过一个倒计时函数让我回想起了PromiseA+规范,今天终于好好研究了一番,也算是对自己的一种查缺补漏,下回合我们再来好好聊一聊PromiseA+规范里面的细则。
欢迎大家对本文指出疑点或留言私信交流

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值