Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
yaofly2012 opened this issue Jun 14, 2020 · 1 comment
Open

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

yaofly2012 opened this issue Jun 14, 2020 · 1 comment

Comments

@yaofly2012
Copy link
Owner

yaofly2012 commented Jun 14, 2020

一、处于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

@yaofly2012
Copy link
Owner Author

yaofly2012 commented Jun 14, 2020

promsie.finally(onFinally)不等价于 promsie.then(onFinally, onFinally)

// Resolve
var promise2 = Promise.resolve(2)
.then( () => {});

promise2.then( value => {
    console.log(`Fulfilled, value=${value}`) // value是undefined
})

var promise2 = Promise.resolve(2)
.finally( () => {});

promise2.then( value => {
    console.log(`Fulfilled, value=${value}`) // value是2
})

// Reject
var promise2 = Promise.reject(2)
.then(() => {}, () => {})

// promise2 依旧是fulfilled
promise2 .then(value => {
    console.log(`Fulfilled, value=${value}`) // // value是undefined
}, reason => {
    console.log(`Rejected, reason=${reason}`)
})

var promise2 = Promise.reject(2).finally(() => {}, () => {});

// promise2也变成rejected
promise2 .then(value => {
    console.log(`Fulfilled, value=${value}`)
}, reason => {
    console.log(`Rejected, reason=${reason}`) // reason是2
})
  1. Promise.prototype.finally()尽量不影响原来的then链,除非onFinally调用发生了异常;
  2. 其他情况(即使返回值是个Promise),也会透传上一个Promise的状态。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant