关于Promise.prototype.then()的一点点细节

869 阅读3分钟

请看下面这段demo

看到这个运行结果,估计大家也看出了错误在哪,我们想要的结果应该是

after 2s
after 3s
finish

但为什么这里第二个then中的p2会在最后才执行呢?

p1().then(() => {
    p2() 
}).then(()=>{
    console.log("finished")
}).catch((err)=>{
    console.log("err",err)
})

在这一段中,then()方法的参数是一个回调,而这个回调其实并没有返回值,只说明then的第一个参数其实是undefined的,但then仍然是接受状态

简单来说这个p2()并没有进入这条Promise链内,只是普通的执行了p2()

而后面的then()会正常进行


那么要怎么修改才能正确实现呢

很简单

只需要让then的回调有返回值就可以了

p1().then(() => {
    return p2()    
}).then(()=>{
    console.log("finished")
}).catch((err)=>{
    console.log("err",err)
})
// 或者
p1().then(p2.then(()=>{
    console.log("finished")
}).catch((err)=>{
    console.log("err",err)
})

Promise.prototype.then()返回值

        var p1 = function(){
           return new Promise((resolve,reject)=>{
               console.log('p1')
               resolve()
           })
        }
        var p2 = function(){
            return new Promise((resolve,reject) => {
                console.log('p2')
                resolve('I am p2 and I m resolved')
            })
        }
        var p3 = function(){
            return new Promise((resolve,reject) =>{
                console.log('p3')
                reject('I am p3 and Im rejected')
            })
        }
        var p4 = function(){
            return new Promise((resolve,reject) => {
                setTimeout(()=>{
                    console.log('p4')
                    // resolve('p4 after 3s resolve')
                    reject('p4 after 3s reject')
                },3000)
            })
        }

对于一个Promise来说,当一个Promise完成(fulfilled)或者失败(rejected),返回函数将被异步调用(由当前的线程循环来调度完成)。具体的返回值依据以下规则返回:

  • 如果then中的回调函数返回一个值,那么then返回的Promise就会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值
// 例子
        p1().then(() => {
            return 'I am return a val'
        }).then((val) => {
            console.log(val) // I am return a val
        })
  • 如果then中的回调函数没有返回值,那么then返回的Promise将会成为接受状态,并且该接受状态的回调函数的参数值为undefined
        p1().then(()=>{
            console.log('nothing return')
        }).then((val)=>{
            console.log(val); // undefined
        })
  • 如果then中的回调函数抛出一个错误,那么then返回的Promise将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值
        p1().then(()=>{
            throw new Error('I am Error')
        }).then(()=>{
            console.log('I am not called') // Not called
        }).catch((err) => {
            console.log('err',err) // err I am Error
        })
  • 如果then中的回调函数返回一个已经是接受状态的Promise,那么then返回的Promise也会成为接受状态,并且将那个Promise的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值
        p1().then(()=>{
            return p2() // 不加return 这个回调将没有返回值,下面val为undefined
        }).then((val) => {
            console.log(val) // I am p2 and I m resolved
        })
  • 如果then中的回调函数返回一个已经是拒绝状态的Promise,那么then返回的Promise也会成为拒绝状态,并且将那个Promise的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值
        p1().then(()=>{
            return p3() // 不加return,这个回调没有返回值,但会调用下个then,val为undefined
        }).then((val)=>{
            console.log(val) // Not called
        }).catch((err)=>{
            console.log('err',err) // err I am p3 and Im rejected
        })
  • 如果then中的回调函数返回一个未定状态(pending)的Promise,那么then返回Promise的状态也是未定的,并且它的终态与那个Promise的终态相同,同时,它变为终态时调用的回调函数参数与那个Promise变为终态时的回调函数的参数是相同的
        p1().then(()=>{
            return p4()
        }).then((val)=>{
            console.log(val)  // p4 resolve -> p4 after 3s resolve
        }).catch((err) => {
            console.log('err',err) // err p4 after 3s reject
        })

如果有误,请各路大神指出嗷 0.0