---
# System prepended metadata

title: "\U0001F3C5 Day 23"
tags: [Node.js 直播班 - 2022 春季班]

---

---
tags: Node.js 直播班 - 2022 春季班
---
# 🏅 Day 23



## 自訂錯誤訊息

我們可以另外新增自定義錯誤訊息的模組，在預期使用者可能會出錯的地方驗證錯誤

**範例**（較完整範例可觀看此 [GitHub](https://github.com/gonsakon/express-week4-sample/blob/week5/service/appError.js)）
```javascript
const appError = (httpStatus, errMessage, next)=>{
    const error = new Error(errMessage);
    error.statusCode = httpStatus;
    error.isOperational = true;
    next(error);
}

module.exports = appError;
```

自訂一個 appError function，將狀態碼及自訂錯誤訊息及 next 參數傳到 function 中
使用 `new Error()` 建立 Error 物件，並設定 Error 回傳的資訊：`statusCode` `isOperational` ，其中 `isOperational` 代表是否為**可預期**的錯誤，因是自訂的錯誤，通常都會設定為 true（可預期）
最後使用 next() 將 Error 交給 app.js 中的錯誤處理 middleware 回傳錯誤訊息

**error handler 範例**
```javascript
// error handler
// 錯誤處理的 middleware 相較一般 middleware 會多一個 err 引數
app.use(function(err, req, res, next) {
  err.statusCode = err.statusCode || 500;
  err.status = err.status || 'error';
  res.status(err.statusCode).json({
    status: err.status,
    message: err.message
  });
});
```


**使用情境(第六週 JWT)**
假設此路由 /posts 是已登入的會員才能造訪的路由，當接收到的 request 是未通過驗證，則可回傳「未登入」的回饋訊息
```javascript
router.get('/', handleErrorAsync(async(req, res, next) =>  {
  // 自訂未通過登入驗證的錯誤
  return next(AppError(401, '您並未登入', next));

  const timeSort = req.query.timeSort == "asc" ? "createdAt":"-createdAt"
  const q = req.query.q !== undefined ? {"content": new RegExp(req.query.q)} : {};
  const post = await Post.find(q).populate({
    path: 'user',
    select: 'name photo'
  }).sort(timeSort);
  res.status(200).json({
    status: 'success',
    results: post.length,
    data: {
      post
    }
  });
}))
```






### 參考資源
[Error - JavaScript | MDN](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Error)

[Express 錯誤處理](https://expressjs.com/zh-tw/guide/error-handling.html)
### 題目（將答案寫在 GitHub 並提交至回報區）
將以下 POST 路由中的註解下方的程式碼改為使用 `appError()` 自訂錯誤資訊，並測試可正確回傳錯誤訊息
routes/posts.js 的 POST 範例

```javascript
router.post('/', async(req, res, next) =>  {
  try {
    const data = req.body;
    if (!data.content) {
      // 將以下改為 appError 自訂錯誤回饋
      res.status(400).json({
        "status": "false",
        "message": "content 欄位為必填"
      });
      return;
    }
    const newPost = await Post.create(
      {
        user: data.user,
        content: data.content,
        tags: data.tags,
        type:data.type
      }
    );
    res.status(200).json({
      status: 'success',
      data: newPost
    });
  } catch (error) {
    next(error);
  }
})
```
可將自己的專案加入 appError.js 自訂錯誤
若沒有也可使用此[專案](https://github.com/dogwantfly/week5-middleware/tree/appError)

回報流程
---
請同學依照下圖教學觀看解答、回報答案:

![](https://i.imgur.com/QtL8zEW.png)

回報格式：請在「回報區」貼上 CodePen 或 HackMD 連結回報答案 (為了統計人數，請同學依序加上「報數」)


<!-- 解答

```javascript
router.post('/', async(req, res, next) =>  {
  try {
    const data = req.body;
    if (!data.content) {
      // 錯誤訊息可自行調整
      return next(appError(400, "欄位未填寫正確：貼文內容為必填", next));
    }
    const newPost = await Post.create(
      {
        user: data.user,
        content: data.content,
        tags: data.tags,
        type: data.type
      }
    );
    res.status(200).json({
      status: 'success',
      data: newPost
    });
  } catch (error) {
    next(error);
  }
})
```


-->

回報區
---

| 報數 | 組別 / 名字          | codepen / hackMD / 其他回饋                                   |
| ---- | -------------------- | ------------------------------------------------------------- |
| 1    | 第 9 組 / 黃士桓     | [HackMD](https://hackmd.io/Ob8MUyHAQJ2JsLDykMdsjw)            |
| 2    | 第 4 組 / 小宥       | [HackMD](https://hackmd.io/o-aXAGf4R8esDzdLh3y4xQ)            |
| 3    | 第 3 組 / HedgehogKU | [HackMD](https://hackmd.io/D5LQSpv8Rh6K3-y7wCAX3A)            |
| 4    | 第 14 組｜East       | [HackMD](https://hackmd.io/_G9m7eyOTku58OTcDxltsg)            |
| 5    | 第 3 組｜hiYifang    | [HackMD](https://hackmd.io/@gPeowpvtQX2Om6AmD-s3xw/B1-H4SULc) |
| 6    | 第 4 組｜苡安        | [HackMD](https://hackmd.io/dr58TfeEQ3WwyX5JWTSysw)            |
| 7    |第 9 組 / konstante  |[HackMD](https://hackmd.io/13Zp-f7STPyB6VXJYBl5kA?both)      |
| 8 |第 5 組 / Hazel |[HackMD@Hazel](https://hackmd.io/@hazelwu/day23) |
| 9 |第 3 組 / Justin |[HackMD](https://hackmd.io/--f8HueeTqanuSJZVpiQuw) |
| 10 |第 2 組 / joe chang |[HackMD](https://hackmd.io/uaRTw9c0TgOrADyXMmGL0Q?view#510-%E8%87%AA%E8%A8%82%E9%8C%AF%E8%AA%A4%E8%A8%8A%E6%81%AF) |
| 11 |第 11 組 / Han Lai |[HackMD](https://hackmd.io/Rv_DBMBsTI2oUeGSBhsy3g?view) |
| 12 |第 1 組 / Claire |[HackMD](https://hackmd.io/bpgaEfUxQvGq9u_pM58gIA) |
| 13 |第 15 組 / Chiu |[HackMD](https://hackmd.io/zieq6cDGTg640q2XXNTN0w?view) |
| 14 |第 7 組 / jason06286 |[HackMD](https://hackmd.io/Yw50AjgPSie5f-Ajumr0nA) |
| 15 |第 1 組 / Ed Huang |[HackMD](https://hackmd.io/Ji-eCdoDR0eY-gVVWagChA?view) |
| 16 | 第 2 組 / Jin |[HackMD](https://hackmd.io/BhN0rhZRTvW0lj7Y2wvfDQ) |
| 17 | 第 3 組 / Hobby |[HackMD](https://hackmd.io/@hobbyling/day23) |
| 18 | 第 12 組 / Jimmy |[HackMD](https://hackmd.io/kGzG8ROKQ5G8_mA8y_1h_g) |
| 19 | 第 15 組 / yolala |[HackMD](https://hackmd.io/4ZCBEAfvSM2ZFKHXzw3ulA) |
| 20 | 第 16 組 / 皓皓 |[HackMD](https://hackmd.io/-ZcbSt1HTEeEViIyts6Vug) |
| 21 | 第 2 組 / wendy | [HackMD](https://hackmd.io/80FIwll1QUa4u0-WoBv-hQ#20220510)|
