共计 3640 个字符,预计需要花费 10 分钟才能阅读完成。
关注公众号 前端小白菜
,更多前端小干货等着你喔!公众号会不定期分享前端技术,每天进步一点点,与大家相伴成长
Promise 的出现,成功的将广大前端开发者从回调地域的深渊中拯救了出来,而后还有 Async/Await,这两者使得开发者更容易编写异步代码,然后当处理错误时,貌似就不是那么的美好了。
先模拟一个请求操作:
const fetchData = (url, shouldReject = false) => {return new Promise((resolve, reject) => {setTimeout(() => {shouldReject ? reject('error') : resolve('this is data');
}, 1000);
});
};
简单回顾一下 Promise 与 Async/Await,例如发起三个请求,使用 Promise 可以
fetchData('url1')
.then(data => {console.log('data1:', data);
return fetchData('url2');
})
.then(data => {console.log('data2:', data);
return fetchData('url3');
})
.then(data => {console.log('data3:', data);
})
.catch(error => console.log('error:', error));
看起来还不错,这也是 Promise 比之回调函数的优势在所在,代码看起来很优雅了,但是 Async/Await 可以更加优雅。
(async () => {const data1 = await fetchData('url1');
console.log('data1:', data1);
const data2 = await fetchData('url2');
console.log('data2:', data2);
const data3 = await fetchData('url3');
console.log('data3:', data3);
})();
代码看起来很优美,甚至 Async/Await 更加像同步代码,也更符合人的正常逻辑了,但是再看下 Promise 的例子,所有的异常都在最后处理,那么出现异常的时候,这个异常是哪个请求的呢?难道还要给错误定义类型不成?
当然 Promise 也可以逐一捕获异常,
fetchData('url1')
.catch(error => console.log('error1:', error))
.then(data => {console.log('data1:', data);
return fetchData('url2', true);
})
.catch(error => console.log('error2:', error))
.then(data => {console.log('data2:', data);
return fetchData('url3');
})
.catch(error => console.log('error3:', error))
.then(data => {console.log('data3:', data);
});
// output
// data1:this is data
// error2:error
// data2:undefined
// data3:this is data
可以看到,虽然可以捕获每一个异常了,但是也由于每一层都做了异常处理,导致 Promise 并不会因为出现 reject 而终止执行,写起来也很麻烦,这不是我们想要的。
Async/Await 是 Promise 的语法糖,我们可以使用 try-catch 来捕获异常,也可以使用 Promise 的 catch 来捕获。
(async () => {
try {const data1 = await fetchData('url1', true);
console.log('data1:', data1);
} catch (error) {console.log('error1:', error);
}
const data2 = await fetchData('url2', true).catch(error => console.log('error2:', error));
console.log('data2:', data2);
const data3 = await fetchData('url3').catch(error => console.log('error3:', error));
console.log('data3:', data3);
})();
// output
// error1: error
// error2:error
// data2:undefined
// data3:this is data
如果使用 Promise 的 catch 来捕获异常,并且对返回值做处理,可以很好的实现异常处理,并且出错阻止往下执行。
(async () => {const data1 = await fetchData('url1', true).catch(error => console.log('error1:', error));
if (!data1) return;
console.log('data1:', data1);
const data2 = await fetchData('url2', true).catch(error => console.log('error2:', error));
if (!data2) return;
console.log('data2:', data2);
const data3 = await fetchData('url3').catch(error => console.log('error3:', error));
if (!data3) return;
console.log('data3:', data3);
})();
// output
// error1: error
那么有没有更优雅一点的写法呢?当然是有的,如果对使用 Promise 的业务函数做一点处理,结合 Promise 与 Async/Await,就可以更加优雅的处理异步业务了。
// 普通未处理的异步函数
const fetchDataPromise = (url, shouldReject = false) => {return new Promise((resolve, reject) => {setTimeout(() => {shouldReject ? reject('error') : resolve('this is data');
}, 1000);
});
};
// 普通异步函数处理
const fetchData = (url, shouldReject = false) => {return new Promise((resolve, reject) => {setTimeout(() => {shouldReject ? resolve(['error', null]) : resolve([null, 'this is data']);
}, 1000);
});
};
// 对异步函数处理
const asyncFunc = (url, shouldReject = false) => {return fetchDataPromise(url, shouldReject)
.then(data => [null, data])
.catch(error => [error, null])
}
// 抽离公共函数处理异步函数
const promiseWrap = (promise) => {
return promise
.then(data => [null, data])
.catch(error => [error, null])
}
有了如上的改造后,业务代码就可以这样写了。
(async () => {const [error1, data1] = await fetchData('url1', true);
if (error1) {console.log('error1:', error1);
// do more thing
}
console.log('data1:', data1);
const [error2, data2] = await asyncFunc('url2', true);
if (error2) {console.log('error2:', error2);
}
console.log('data2:', data2);
const [error3, data3] = await promiseWrap(fetchDataPromise('url3', true));
if (error3) {console.log('error3:', error3);
}
})();
// output
// error1: error
// data1: null
// error2: error
// data2: null
// error3: error
// data3: null
这样写就优雅多了,也更加容易处理异常,其实这种处理方法在 GO 语言中非常常见。