關注公衆號前端小白菜
,更多前端小乾貨等着你喔!公衆號會不按期分享前端技術,天天進步一點點,與你們相伴成長前端
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語言中很是常見。
本文首發於本人公衆號,前端小白菜,分享與關注前端技術,歡迎關注~~