关注公众号前端小白菜
,更多前端小干货等着你喔!公众号会不按期分享前端技术,天天进步一点点,与你们相伴成长前端
Promise的出现,成功的将广大前端开发者从回调地域的深渊中拯救了出来,然后还有Async/Await,这二者使得开发者更容易编写异步代码,而后当处理错误时,貌似就不是那么的美好了。promise
先模拟一个请求操做:异步
const fetchData = (url, shouldReject = false) => { return new Promise((resolve, reject) => { setTimeout(() => { shouldReject ? reject('error') : resolve('this is data'); }, 1000); }); };
简单回顾一下Promise与Async/Await,例如发起三个请求,使用Promise能够async
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的例子,全部的异常都在最后处理,那么出现异常的时候,这个异常是哪一个请求的呢?难道还要给错误定义类型不成?fetch
固然Promise也能够逐一捕获异常,this
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而终止执行,写起来也很麻烦,这不是咱们想要的。url
Async/Await是Promise的语法糖,咱们可使用try-catch来捕获异常,也可使用Promise的catch来捕获。spa
(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来捕获异常,而且对返回值作处理,能够很好的实现异常处理,而且出错阻止往下执行。code
(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语言中很是常见。
本文首发于本人公众号,前端小白菜,分享与关注前端技术,欢迎关注~~