# 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` 並造成瀏覽器卡住


這時我們需要自己做一個 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 資訊給瀏覽器了 !

:::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
:::
==沒反應==

==沒 userId==

==回傳 user 資料==

## 參考資料
- [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/)