简要介绍:ES6中为了处理异步,增加了promise、generator和async,它们各自都有不同的内部错误处理方式,本文总结一下promise、generator和async的内部错误处理方法。
1 . Promise的错误处理方法
(1) 在Promise的构造体内进行错误处理
var promise=new Promise(function(resolve,reject){
try {
throw new Error('test');
}catch(e){
reject(e)
}
})
在Promise的构造体内进行错误处理,类似于我们在ES5中的错误处理方式。
(2)通过Promise.prototype.catch来进行错误处理
生成Promise实例后,我们可以通过Promise原型上的catch方法来捕获Promise实例内部的错误。
var promise=new Promise(function(resolve,reject){
reject(new Error('test'));
})
promise.catch(function(e){
//something to deal with the error
console.log(e)
})
上述的例子,跟(1)中是类似的,此外catch方法还可以处理链式调用中的错误,比如:
var promise=new Promise(function(resolve,reject){
resolve();
})
promise.then(function(){
// if some error throw
}).then(function(){
// if some error throw
}).catch(function(e){
//something to deal with the error
console.log(e)
})
// Error : test1
上述的代码中,最后一个catch方法可以捕获前面链式调用过程中任何一步then方法里面所抛出的错误。
catch方面里面还可以再抛错误,这个错误会被后面的catch捕获
var promise=new Promise(function(resolve,reject){
reject(new Error('test1'))
})
promise.catch(function(e){
console.log(e);
throw new Error('test2')
}).catch(function(e){
console.log(e)
})
// Error : test1
// Error : test2
(3)Promise.all中的错误处理
如果组成Promise.all的promise有自己的错误捕获方法,那么Promise.all中的catch就不能捕获该错误。
var p1=new Promise(function(resolve,reject){
reject(new Error('test1'))
}).catch(function(e){
console.log("由p1自身捕获",e);
})
var p2=new Promise(function(resolve,reject){
resolve();
})
var p=Promise.all([p1,p2]);
p.then(function(){
}).catch(function(e){
//在此处捕获不到p1中的error
console.log(e)
})
//由p1自身捕获 Error: test1
(4)Promise.try中的错误捕获
ES2018中可以通过Promise.try来同步处理,可能是异步也可能是同步的函数。
function f(){}
Promise.try(f);
console.log(2);
上述的f方法,不管是同步还是异步,都会执行该方法,再输出2。
在Promise.try的错误处理中,通过catch方法既可以捕获f是同步函数情况下的错误,也可以捕获f是异步函数情况下的错误。
function f(){}
Promise.try(f).then(function(){
}).catch(function(e){
})
(5)在promise中无法被捕获的错误
在promise实例resolve之后,错误无法被捕获。
var promise=new Promise(function(resolve,reject){
resolve();
throw new Error('test');//该错误无法被捕获
})
promise.then(function(){
//
}).then(function(e){
console.log(e)
})
该错误可以用尾调用resolve来避免。
2 .Generator中的错误处理方法
(1)构造体内部捕获
function * F(){
try{
yield 1
}catch(e){
console.log(e)
}
}
var f=F();
f.throw(new Error('test1'))
上述这样在内部不能捕获到test1错误,为什么呢? 这个generator的原理有关,调用F()仅仅返回一个状态生成器,并没有执行generator里面的方法,因此在f上直接跑错误是无法捕获的。
那么怎么才能捕获错误呢?采用如下的方式:
function * F(){
try{
yield 1
}catch(e){
console.log(e)
}
}
var f=F();
f.next()//增加了一句next执行,可以执行generator里面的内容
f.throw(new Error('test1'))
//捕获错误 Error test1
这样就能捕获该错误。
此外捕获错误后,会执行一次next方法
function * F(){
try{
yield 1
}catch(e){
console.log(e)
}
yield 2
return 3
}
var f=F();
f.next(); //{value :1,done:false}
f.throw(new Error('test1')) //{value:2,done:false}
f.next(); //{value:3,done:true}
(2)在Generator构造体外部捕获错误
function F(){
yield 1;
yield 2;
return 3;
}
var f=F();
try{
f.throw(new Error('test1'))
}catch(e){
console.log(e)
}
// Error test1
在构造体外部捕获,可以直接f.throw
(3)如果Generator的错误没有被捕获,就不会继续执行
function F(){
yield 1;
throw new Error('test1');
yield 2;
return 3
}
var f=F();
f.next() // {value:1,done:false}
f.next() // {value:undefined,done:true}
上述例子中,只要错误没有被处理,就会返回done:true就停止执行generator
3 .async/await中的错误处理
(1)async中的错误处理
因为async的返回值也是个promise,跟promise的错误处理差不多。
此外,async里面throw Error 相当于返回Promise.reject。
async function F(){
throw new Error('test1')
}
var f=F();
f.catch(function(e){console.log(e)});
// Error:test1
(2)await中的错误处理
在async中,await的错误相当于Promise.reject
async function F(){
await Promise.reject('Error test1').catch(function(e){
console.log(e)
})
}
var f=F(); // Error:test1
(3)await中的promise.reject必须要被捕获
await如果返回的是reject状态的promise,如果不被捕获,就会中断async函数的执行。
async function F(){
await Promise.reject('Error test1');
await 2
}
var f=F()
上述代码中,前面的Promise.reject没有被捕获,所以不会执行await 2
4.总结
(1)Promise、generator错误都可以在构造体里面被捕获,而async/await返回的是promise,可以通过catch直接捕获错误。
(2)generator 抛出的错误,以及await 后接的Promise.reject都必须被捕获,否则会中断执行。