你好,我是南一。这是我在准备面试八股文的笔记,如果有发现错误或者可完善的地方,还请指正,万分感谢🌹
前言:今天做项目时,遇到
Promise
抛出错误捕获不到的情况,然后我就去找了,阮一峰ES6入门重新学了一遍,又加深了对Promise
的理解,分享给大家,望斧正!
先来看一段代码,创建一个Promise实例,状态设置为成功fulfilled
const pro = new Promise((resolve, reject) => {
resolve('我成功啦')
})
pro.then((res) => {
console.log("then: " + res);
}).catch((err) => {
console.log('catch: ' + err);
})
//运行结果//then: 我成功啦
往Promise
构造函数传入一个函数,函数有两个参数:
resolve
:resolve
函数的作用是,将Promise
对象的状态从“未完成”变为“成功” (即从 pending 变为fulfilled
),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject
:reject
函数的作用是,将Promise
对象的状态从“未完成”变为“失败” (即从 pending 变为rejected
),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
我成功啦
通过resolve
函数,传递出去,被then
方法接收到,then
方法第一个参数是fulfilled
状态的回调函数,所以就将 我成功啦
作为参数 res 打印出 then: 我成功啦
如果传入的函数抛出错误呢?
const pro = new Promise((resolve, reject) => {
//resolve('我成功啦')
throw Error('请求超时')
})
pro.then((res) => {
console.log("then: " + res);
}).catch((err) => {
console.log("catch: " + err);
})
//运行结果//catch: Error: 请求超时
现在我要把pro对象状态改变后的结果传递出去:我用returnPromise
函数将pro对象调用then或catch方法后的结果 return 出去
const pro = new Promise((resolve, reject) => {
//resolve('我成功啦')
throw Error('请求超时')
})
function returnPromise() {
return pro.then((res) => {
console.log("then: " + res);
return res
}).catch((err) => {
console.log('catch: ' + err);
return err;
})
}
returnPromise().then((res) => {
console.log('returnPromise then resolve: ' + res);
}).catch((err) => {
console.log('returnPromise catch: ' + err);
})
//运行结果 //catch: Error: 请求超时
//returnPromise then resolve: Error: 请求超时
诶,有点奇怪,抛出的错误在returnPromise
内会被catch
捕获到,而在外部调用后是在then
方法内打印出来。
这里千万别搞混了,pro对象此时的状态是rejected
,所以被catch
捕获到,这很合理
解释:
Promise.prototype.catch()
方法是.then(null, rejection)
或.then(undefined, rejection)
的别名,用于指定发生错误时的回调函数。
pro对象调用catch
方法后返回,一个新的Promise
对象(这里的catch方法其实就是then方法,因此也是返回一个新的Promise
对象)
解释:
then
方法返回的是一个新的Promise
对象(注意,不是原来那个Promise
实例)。因此可以采用链式写法,即then
方法后面再调用另一个then
方法。
因此,这个新的Promise
对象调用then
方法而不调用catch
方法,是因为其状态为fulfilled
(这里我还不知道为什么是fulfilled
状态)
查完原因回来了 😁
根据Promise A+
规范 (注释中的数字就是规范里的序号) then
方法必须返回一个新的Promise
对象
promise2 = promise1.then(onFulfilled, onRejected); //2.2.7
- 如果
then
方法里的两个参数onFulfilled
或onRejected
其中一个返回一个值x
,则运行 Promise Resolution Procedure[[Resolve]](promise2, x)
。
- 如果其中一个
onFulfilled
或onRejected
抛出异常e
,则promise2
必须以e
为理由来进入rejected
状态。
- 如果
onFulfilled
不是一个函数且promise1
状态为fulfilled
,promise2
必须是fulfilled
状态,且跟promise1
有着一样的value
- 如果
onRejected
不是一个函数且promise1
状态为rejected
,promise2
必须是rejected
状态,且跟promise1
有着一样的reason
"value” is any legal JavaScript value (including
undefined
, a thenable, or a promise).“reason” is a value that indicates why a promise was rejected.
所以,pro对象调用catch
方法后,catch
方法return err
,符合了第 1 点规则,因此,调用returnPromise()
直接返回一个fulfilled
状态的 Promise 对象,且参数为err
怎么让returnPromise
方法调用后走catch
方法呢?
在returnPromise
内部调用catch
方法后,返回一个rejected
状态的Promise
实例对象
const pro = new Promise((resolve, reject) => {
throw Error('请求超时')
})
function returnPromise() {
return pro.then((res) => {
console.log("then: " + res);
return res
}).catch((err) => {
console.log('catch: ' + err);
//return err;
return Promise.reject(err) //2.3.2
})
}
returnPromise().then((res) => {
console.log('returnPromise then resolve: ' + res);
}).catch((err) => {
console.log('returnPromise catch: ' + err);
})
//运行结果 //catch: Error: 请求超时
//returnPromise catch: Error: 请求超时
pro对象catch
方法返回一个值x
(这里x
为Promise.reject(err)
,一个rejected
状态的Promise
对象) 则执行[[Resolve]](promise, x)
,并把新的promise
对象的状态,置为跟x
一样的rejected
状态
那么如果在then
方法内加上rejected
状态的回调函数会怎么样呢?
前面我们说:Promise.prototype.catch()
方法是.then(null, rejection)
或.then(undefined, rejection)
的别名,用于指定发生错误时的回调函数。
const pro = new Promise((resolve, reject) => {
throw Error('请求超时')
// resolve('我成功啦')
})
function returnPromise() {
return pro.then((res) => {
console.log("then: " + res);
return res
}).catch((err) => {
console.log('catch: ' + err);
// return err;
return Promise.reject(err)
})
}
returnPromise().then((res) => {
console.log('returnPromise then resolve: ' + res);
}, (rej) => {
console.log('returnPromise then reject: ' + rej);
}).catch((err) => {
console.log('returnPromise catch: ' + err);
})
//运行结果 //catch: Error: 请求超时
//returnPromise then reject: Error: 请求超时
结果是在then
方法内rejected
状态的回调函数捕获到错误