1. try...catch...捕获异常逻辑
- 多层
try...catch...,错误会被距离最近的catch捕获
try {
try {
throw new Error("oops");
}
catch (ex) {
console.error("inner", ex.message);
}
finally {
console.log("finally");
}
}
catch (ex) {
console.error("outer", ex.message);
}
// Output:
// "inner" "oops"
// "finally"
- 在内层catch中再次抛出错误,会被外层捕获
try {
try {
throw new Error("oops");
}
catch (ex) {
console.error("inner", ex.message);
throw ex;
}
finally {
console.log("finally");
}
}
catch (ex) {
console.error("outer", ex.message);
}
// Output:
// "inner" "oops"
// "finally"
// "outer" "oops"
- 从 finally 语句块返回
try {
try {
throw new Error("oops");
}
catch (ex) {
console.error("inner", ex.message);
throw ex;
}
finally {
console.log("finally");
return;
}
}
catch (ex) {
console.error("outer", ex.message);
}
// Output:
// "inner" "oops"
// "finally"
因为 finally 块里的 return 语句,"oops" 没有抛出到外层,从 catch 块返回的值同样适用
2. 异步下的错误拦截问题
监听Promise错误透出: unhandledrejection
1. 请求函数不做catch处理
const func1 = () => {
return new Promise((resolve, reject)=> {
setTimeout(() => {
reject('失败')
}, 1000)
})
}
const func2 = async () => {
try {
const a = await func1();
console.log('a', a);
} catch (e) {
console.log('func2 catch', e);
}
}
func2();
// func2 catch 失败
2. 请求函数做catch处理
const func1 = () => {
return new Promise((resolve, reject)=> {
setTimeout(() => {
reject('失败')
}, 1000)
}).catch((e) => {
console.log('func1 catch', e)
})
}
const func2 = async () => {
try {
const a = await func1();
console.log('a', a);
} catch (e) {
console.log('func2 catch', e);
}
}
func2();
// func1 catch 失败
3. 在catch中返回值
- 返回reject
const func1 = () => {
return new Promise((resolve, reject)=> {
setTimeout(() => {
const error = new Error('fail');
reject(error);
}, 1000)
}).then((data) => {
console.log('func1 then', data);
// 必须return
return Promise.resolve(data);
})
.catch((e) => {
console.log('func1 catch', e)
// 如果是resolve,则走到正常逻辑
return Promise.reject('func1:fail')
})
}
const func2 = async () => {
try {
const a = await func1();
console.log('a', a);
} catch (e) {
console.log('func2 catch', e);
}
}
func2()
// func1 catch Error: fail
// func2 catch func1:fail
等同于
const func1 = () => {
return new Promise((resolve, reject)=> {
setTimeout(() => {
const error = new Error('fail');
reject(error);
}, 1000)
})
}
const func2 = async () => {
return new Promise((resolve, reject)=> {
func1()
.then((data) => {
console.log('func1 then', data);
resolve(data);
})
.catch((e) => {
console.log('func1 catch', e)
reject('func1:fail')
})
})
}
const func3 = async () => {
try {
const a = await func2();
console.log('a', a);
} catch (e) {
console.log('func3 catch', e);
}
}
func3();
// func1 catch Error: fail
// func3 catch func1:fail
- 返回resolve
const func1 = () => {
return new Promise((resolve, reject)=> {
setTimeout(() => {
// const error = new Error('fail');
// reject(error);
resolve(1000);
}, 1000)
}).then((data) => {
console.log('func1 then', data);
return Promise.reject(data);
})
.catch((e) => {
console.log('func1 catch', e)
// 如果是resolve,则走到正常逻辑
return Promise.resolve(2000);
// return Promise.reject('func1:fail')
})
}
const func2 = async () => {
try {
const a = await func1();
console.log('a', a);
} catch (e) {
console.log('func2 catch', e);
}
}
func2()
如果直接返回一个值相当于return Promise.resolve(值)
- finally
const func1 = () => {
return new Promise((resolve, reject)=> {
setTimeout(() => {
// const error = new Error('fail');
// reject(error);
resolve(1000);
}, 1000)
}).then((data) => {
console.log('func1 then', data);
return Promise.reject(data);
})
.catch((e) => {
console.log('func1 catch', e)
// 如果是resolve,则走到正常逻辑
// return Promise.resolve(2000);
return Promise.reject('func1:fail')
})
.finally(() => {
console.log('finally');
return Promise.resolve(3000);
})
}
const func2 = async () => {
try {
const a = await func1();
console.log('a', a);
} catch (e) {
console.log('func2 catch', e);
}
}
// func1 then 1000
// func1 catch 1000
// finally
// func2 catch func1:fail
finally里为reject时,finally返回值优先级最高,否则为catch。这块还没搞懂???
4. 无效的try...catch...
1. 没有运行的函数
const func1 = () => {
return new Promise((resolve, reject)=> {
setTimeout(() => {
const error = new Error('fail');
reject(error);
}, 1000)
})
}
const func2 = async () => {
try {
return new Promise((resolve, reject)=> {
func1()
.then((data) => {
console.log('func1 then', data);
resolve(data);
})
.catch((e) => {
console.log('func1 catch', e)
reject('func1:fail')
})
})
} catch (e) {
console.log('func2 catch', e);
}
}
const func3 = async () => {
try {
const a = await func2();
console.log('a', a);
} catch (e) {
console.log('func3 catch', e);
}
}
func3();
// func1 catch Error: fail
// func3 catch func1:fail
const func1 = () => {
try {
return function a() {
const a = 1;
console.log('a', a.b.c);
}
} catch (e) {
console.log('func1 catch', e);
}
}
const func2 =() => {
try {
func1()();
} catch (e) {
console.log('func2 catch', e);
}
}
func2();
// func2 catch TypeError
const func1 = () => {
return function a() {
try {
const a = 1;
console.log('a', a.b.c);
} catch (e) {
console.log('func1 catch', e);
}
}
}
const func2 =() => {
try {
func1()();
} catch (e) {
console.log('func2 catch', e);
}
}
func2();
// func1 catch TypeError
2. 重复包裹
const func2 = async () => {
try {
const a = await new Promise((resolve, reject)=> {
func1()
.then((data) => {
console.log('func1 then', data);
resolve(data);
})
.catch((e) => {
console.log('func1 catch', e)
// reject('func1:fail')
})
})
console.log('a', a);
} catch (e) {
console.log('func2 catch', e);
}
}
// func1 catch Error: fail
3. 避免太多try...catch...
1. 直接catch
- 不会中断逻辑
- 错误不会透出
function func1 () {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('请求异常')
}, 1000)
})
}
async function func2 () {
let data = await func1().catch(e => console.warn(e))
// 执行没有中断,userInfo 为 undefined
if (!data) return // 需要做非空校验
console.log('data', data);
}
2. reject中断执行
- 会中断逻辑
- 错误会透出
function func1 () {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('请求异常')
}, 1000)
})
}
async function func2 () {
let data = await func1().catch(e => {
console.warn(e)
return Promise.reject(e)
})
// 执行被中断,userInfo 为 undefined
console.log('data', data);
}
3. await-to-js
export function to<T, U = Error>(
promise: Promise<T>,
errorExt?: object
): Promise<[U, undefined] | [null, T]> {
return promise
.then<[null, T]>((data: T) => [null, data])
.catch<[U, undefined]>((err: U) => {
if (errorExt) {
const parsedError = Object.assign({}, err, errorExt)
return [parsedError, undefined]
}
return [err, undefined]
})
}
export default to
函数to接受参数Promise和errorExt,如果这个 Promise 成功时返回[null, data],如果异常时会判断是否带有errorExt参数(代表传递给 err 对象的附加信息),如果有时会与 catch 捕获的 err 合并返回,如果没有时返回[err, undefined]