Skip to content

JS-ES6-Promise.prototype.then链的误区 #143

Open
@yaofly2012

Description

@yaofly2012

一、处于then链中Promise对象的状态跟其前一个Promise对象的状态没有直接关系

即:
var promise2 = promise1.then(onFulfilled, onRejected)表达式中promise2的状态跟promise1没有直接关系。

// 创建promise1对象
var promise1 = new Promise((resolve, reject) => {
    reject('Rejected')
})

// 创建promise2对象,来自`promise1.then`的返回值
var promise2 = promise1.then(value => {
    console.log(`[promise1]: fulfilled, value='${value}'`)
}, reason => {
    console.log(`[promise1]: rejected, reason='${reason}'`)
})

promise2.then(value => {
    console.log(`[promise2]: fulfilled, value='${value}'`)
}, reason => {
    console.log(`[promise2]: rejected, reason='${reason}'`)
})

输出:

[promise1]: rejected, reason='Rejected'
[promise2]: fulfilled, value='undefined'

此DEMO中即使promise1变成了rejected,但是 promise2却是fulfilled状态。

1.2 分析promise2 = promise1.then(onFulfilled, onRejected)

  • promise1的终态只是直接决定调用onFulfilled还是onFulfilled回调函数。
  • promise2的状态受onFulfilled OR onRejected回调函数影响:

1. 如果没有onFulfilled/onRejected回调函数:

如promise1是fulfilledrejected)且没有onFulfilledonRejected)回调函数,,此时promise2采用promise1的状态(即promise2的状态跟promise1的状态一致):

var promise1 = new Promise((resolve, reject) => {
    reject('Rejected')
})
// promise1没有注册`onRejected`回调函数
var promise2 = promise1.then()

promise2.then(value => {
    console.log(`[promise2]: fulfilled, value='${value}'`)
}, reason => {
    console.log(`[promise2]: rejected, reason='${reason}'`)
})

输出:

[promise2]: rejected, reason='Rejected'
var promise1 = new Promise((resolve, reject) => {
    resolve('Fulfilled')
})
// promise1没有注册`onFulfilled`回调函数
var promise2 = promise1.then()

promise2.then(value => {
    console.log(`[promise2]: fulfilled, value='${value}'`)
}, reason => {
    console.log(`[promise2]: rejected, reason='${reason}'`)
})

输出:

[promise2]: fulfilled, value='Fulfilled'

2. 如果 onFulfilled/onRejected执行过程中抛出了异常:

此时Reject promise2对象,并且把异常作为reason。

var promise1 = new Promise((resolve, reject) => {
    resolve('Fulfilled')
})

// promise1的`onFulfilled`回调函数抛出了异常
var promise2 = promise1.then(() => {
    throw new Error('A Error in onFulfilled func')
})

promise2.then(value => {
    console.log(`[promise2]: fulfilled, value='${value}'`)
}, reason => {
    console.log(`[promise2]: rejected, reason='${reason}'`)
})

输出:

[promise2]: rejected, reason='Error: A Error in onFulfilled func'

3. 如果onFulfilled/onRejected函数的返回值是x

如果onFulfilled/onRejected函数正常执行完,且返回值是x(如果没有显示指定返回值,则x为undefined)。

3.1 如果x也是个Promise对象,则promise2采用x的状态:

var promise1 = new Promise((resolve, reject) => {
    resolve('Fulfilled')
})

// promise1的`onFulfilled`回调函数返回`promise1`对象
var promise2 = promise1.then(() => {
    return promise1;
})

promise2.then(value => {
    console.log(`[promise2]: fulfilled, value='${value}'`)
}, reason => {
    console.log(`[promise2]: rejected, reason='${reason}'`)
})

输出:

[promise2]: fulfilled, value='Fulfilled

此时promise2promise1具有相同的状态和相同的value。

3.2 如果xpromise2相等,则抛出TypeError异常:

上个规则成立的前提就是xpromise2不能相等,否则就会产生互相依赖的矛盾。
如果xpromise2相等,则抛出TypeError异常,并且作为promise2对象rejected状态的reason。

var promise1 = new Promise((resolve, reject) => {
    resolve('Fulfilled')
})

// promise1的`onFulfilled`回调函数返回了`promise2`
var promise2 = promise1.then(() => {
    return promise2;
})

promise2.then(value => {
    console.log(`[promise2]: fulfilled, value='${value}'`)
}, reason => {
    console.log(`[promise2]: rejected, reason='${reason}'`)
})

输出:

[promise2]: rejected, reason='TypeError: Chaining cycle detected for promise #<Promise>'

3.3 如果x是个thenable对象:

则执行大致下面的流程:

var then = x.then;
then.call(x, resolve, reject);
  • 如果x.then内部先调用了resolve(y),则进行[[Resolve]](promise, y)
    此时会开启新的Promise解析过程,y千万不能和x相等,否则会产生无限循环。
  • 如果x.then内部先调用了rejected(y), 则promise2也变成rejected,并且把y作为reason;
  • 如果x.then内部先抛了异常, 则promise2也变成rejected,并且把异常作为reason;

3.4 其他情况(即x不是Promise对象,也不是thenable对象):

promise2变成fulfilled,并且把x作为其value。
如同开头的DEMO中即使promise1变成了rejected,但是 promise2却是fulfilled状态
因为promise1onRejected回调函数的返回值xundefined所以promise2的value是undefined

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions