Promise的错误处理
距离上一次写 blog 已经又过去了两月有余,一周一篇的目标很难到达呀,借口就不找了,尽力弥补吧。
今天我们来说一说 Promise 的错误处理,随着 ES6(aka ES2015) 开始普及,以及越来越多的 Nodejs 应用出现,Promise 作为处理异步的一种重要工具,在我们日常的工作中使用也越来越频繁,本文不准备就 Promise 的基本概念及功能作一些描述,推荐两篇文章(MDN Promise, We have a problem with promises中文)足以让你对Promise非常了解。
我们今天专门讲一下 Promise 的错误处理。
promise.then
方法接收两个回调函数为参数,其中第一个为成功回调函数,第二个为失败回调函数,需要注意的是
这儿的两个回调函数基于promsie
这个 Promise 实例的处理结果的,比如:
Promise.reject(new Error('jser down'))
.then(() => {
console.log('never here')
}, (err) => {
console.log(err.message) // jser down
})
如果你想捕捉 then
的成功回调函数的错误,那需要再写一个 then
加上失败的错误回调,简而言之就是:then
里的错误处理函数是对上一个处理过程的错误捕捉。
那么,对于一个常见的错误处理可能是这样的:
Promise.resolve('a:1')
.then(JSON.parse)
.then((json) => {
console.log(json)
}, (err) => {
//这儿捕获的是上一个JSON.parse时的错误
console.log(err.message) //Unexpected token a
})
常见的一级一级的异步处理任务,用这种错误捕捉代码就显得太难看了,打码效率也低效了,应好有 catch
来统一处理:
Promise.resolve('{"a":1}')
.then(JSON.parse)
.then((json) => {
return Promise.resolve(json.a++)
})
.then((a) => {
return Promise.reject(new Error('error 1'))
})
.then(() => {
return Promise.reject(new Error('error 2'))
})
.catch((err) => {
console.log(err.message) //error 1
})
catch
很方便的解决了我们对于多级 Promise
处理的问题,那对于一些忘记加或者无法加 catch
的情况怎么处理呢?庆幸的是 API 的设计者们又为我们这些应用开发者想好了,有一个全局的事情叫
unhandledRejection
这个事件在浏览器( Chrome 49+ )和 Nodejs 里名称稍微有点不一样,浏览器里是全小写的
unhandledrejection
。 比如:
process.on('unhandledRejection', function (reason, promise) {
console.log(reason) // [Error: unhandledrejection]
console.log(promise) // Promise { <rejected> [Error: unhandledrejection] }
})
setTimeout(() => {
Promise.reject(new Error('unhandledrejection'))
}, 1000)
在浏览器里,我们需要 window.addEventListener("unhandledrejection", (e)=>{})
,在
Web Workers 里需要使用 self.addEventListener
,我们来写一个简单的小模块,把 Nodejs 、浏览器以及
Web Workers 里的情况统一一下:
const onUnhandledRejection = (function () {
const isNode = typeof process === 'object' &&
Object.prototype.toString.call(process) === '[object process]'
if (isNode) {
return function (cb) {
process.on('unhandledRejection', cb)
}
}
return function (cb) {
self.addEventListener('unhandledrejection', (ev) => {
cb(ev.reason, ev.promise)
})
}
})()
/* 使用:
onUnhandledRejection((r,p) => {
console.log(r)
})
*/
OK ,今天的小文就到此为止啦。