# Express : 接住 async 函式拋出的錯誤 ###### tags: `w3HexSchool` . `express.js` > 在 express 中常常會有等 A 做完再做 B 的情況 > ( ex : 身分驗證後 => 從 DB 中取資料 => 回傳資料 ) > 造成出現長長的 .then().catch() 下方的流程是 `auth` => `getUser` => `res.json` 需要花一些時間 , 才能了解函數中有幾個動作 & 其執行順序 ```javascript= router.get('/longThing', (req, res, next) => { const {token, userId} = req.query; auth(token) .then(authObj => { if (authObj.authed) return getUser(userId); else throw new Error('fail to auth'); }) .then(user => { if (user) return res.json(user); else throw new Error('cannot find user'); }) .catch(err => next(err)); }); ``` 如果改成 `async` 模式 , 也許較易理解有幾個動作 & 其執行順序 ```javascript= router.get('/longThingAsync', async (req, res, next) => { const {token, userId} = req.query; const authObj = await auth(token); if (!authObj.authed) throw new Error('fail to auth'); else { const user = await getUser(userId); if (user) res.json(user); else throw new Error('cannot find user'); } }); ``` ***BUT*** 在 `async` 函式下 , 當程式拋出 Error 時 , express 並不會接住此 Error , 最後會拋出 `UnhandledPromiseRejectionWarning` 並造成瀏覽器卡住 ![](https://i.imgur.com/VlKfWJT.png) ![](https://i.imgur.com/LLkKZtq.png) 這時我們需要自己做一個 errorWrapper 去接住 error 並將 error 傳給 express 去處理 ```javascript= const errorWrapper = fn => (...args) => fn(...args).catch(args[2]); router.get('/longThingWrapped', errorWrapper(async (req, res, next) => { const {token, userId} = req.query; const authObj = await auth(token); if (!authObj.authed) throw new Error('fail to auth'); else { const user = await getUser(userId); if (user) res.json(user); else throw new Error('cannot find user'); } })); ``` 之後 express 就會正常回傳 error 資訊給瀏覽器了 ! ![](https://i.imgur.com/XXZCCgy.png) :::info 目前看來 `errorWrapper` 是一個看不懂的神奇函式 , 讓我們來改寫一下 , 讓其更加的語意清晰 ::: ```javascript= // 改寫 const errorWrapper = function (func) { return function (req, res, next) { func(req, res, next).catch(err => next(err)); } }; ``` 之後我們就可以愉快的在 `express` 中使用 `async` 函式了 ! ## 成果 :::info 利用下方網址查看成果 <br/><br/> - 沒反應 : https://1dbl5.sse.codesandbox.io/user/longThingAsync - 沒 userId : https://1dbl5.sse.codesandbox.io/user/longThingWrapped?token=t - 回傳 user 資料 : https://1dbl5.sse.codesandbox.io/user/longThingWrapped?token=t&userId=1 ::: ==沒反應== ![](https://i.imgur.com/t8wzj4g.png) ==沒 userId== ![](https://i.imgur.com/SAawglk.png) ==回傳 user 資料== ![](https://i.imgur.com/qB5kgLg.png) ## 參考資料 - [how to handle UnhandledPromiseRejectionWarning in express](https://stackoverflow.com/questions/43564222/how-to-handle-unhandled-promise-rejection-in-async-object-method-in-node-js-expr) - [wrapping-javascript-callbacks](http://tlrobinson.net/blog/2008/10/wrapping-javascript-callbacks/)