---
# System prepended metadata

title: Todolist RESTful API - CRUD API

---

六角體驗營
# Todolist RESTful API : 開發新刪修查的API (實作3) - POST API 資料錯誤樣態
[**Todolist RESTful API : 開發新刪修查的API (實作2) - CRUD ( GET / POST  API )**](https://hackmd.io/fjk5zVcFRwaVnQND2iUNfQ?view)

<br>

## 11. 新增 POST API 異常行為
> try catch 捕捉錯誤
> * [**個人筆記**](https://hackmd.io/c2KkZRulQ2-AdBIXNds43w?view#try-catch-%E6%8D%95%E6%8D%89%E9%8C%AF%E8%AA%A4%E7%95%B0%E5%B8%B8%E8%A1%8C%E7%82%BA)
> * [**mdn docs**](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Statements/try...catch)

### 錯誤樣態 : 格式錯誤 
**格式錯誤1. POST資料非JSON格式 -> JSON.parse 無法解析 )**
 
* #### STEP 11-1. 將 try...catch 在POST方法中執行

  * try 區塊放正確應執行的內容(可能拋出錯誤)
  * catch 區塊印出 error 錯誤資訊 
  
  ```js=
    const http = require('http');
    const todos = [
        // 清空，之後以POST方式新增
    ]
    
    const requestListener = (request,response)=>{
        const headers = {
          'Access-Control-Allow-Headers': 'Content-Type, Authorization, Content-Length, X-Requested-With',
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Methods': 'PATCH, POST, GET,OPTIONS,DELETE',
          'Content-Type': 'application/json'
        };
        
        let body ="";
        request.on('data',(chunk)=>{ 
            body += chunk; 
        })
        if(request.url=='/todolist' && request.method == "GET"){
            response.writeHead(200,headers); 
            response.write(JSON.stringify({
                "status":"success",
                data:todos,  
            }));
            response.end();
    //POST方法-------------------------------------------------------
        }else if(request.url=='/todolist' && request.method == "POST"){
            
            request.on('end',()=>{
                //try...catch------------------
                try{              // 這裡有可能拋出錯誤
                    const title = JSON.parse(body).title; 
                    console.log(title); 
                    const todo = {
                        "title":title, 
                        "id":uuidv4()
                    }
                    todos.push(todo);

                    response.writeHead(200,headers); 
                    response.write(JSON.stringify({
                        "status":"success",
                        data:todos,  
                    }));
                    response.end();  //回傳結束
                
                }catch(error){  // 處理錯誤
                    console.log(error,"程式錯誤") //error會印出錯誤資訊
                    response.end();  //回傳結束
                }
                
            })
     //-----------------------------------------------------------------
            
        }else if(request.method == "OPTIONS"){ 
            response.writeHead(200,headers); 
            response.end(); 
        }else{  
            response.writeHead(404,headers); 
            response.write(JSON.stringify({
                "status":"fail",
                "message":"查無此路由",
            }));
            response.end();
        }
      };

      const server = http.createServer(requestListener);
      server.listen(3005);
  ```
  
  * postman POST 非JSON內容 ` { `  
    -> 執行catch區塊，erminal 會回傳錯誤代碼(下圖)
  
    ![](https://hackmd.io/_uploads/HyyqQTLMa.png)
    
* #### STEP 11-2. 進一步修改 catch 區塊執行程式
  ```js=
  //POST方法-------------------------------------------------------
        }else if(request.url=='/todolist' && request.method == "POST"){
            
            request.on('end',()=>{
                //try...catch------------------
                try{             
                    const title = JSON.parse(body).title; 
                    console.log(title); 
                    const todo = {
                        "title":title, 
                        "id":uuidv4()
                    }
                    todos.push(todo);

                    response.writeHead(200,headers); 
                    response.write(JSON.stringify({
                        "status":"success",
                        data:todos,  
                    }));
                    response.end();  //回傳結束
                
                    
                //修改為回傳錯誤資訊給使用者-----------------
                }catch(error){ 
                    response.writeHead(400,headers); //400 bad request 錯誤請求 (格式錯誤)
                    response.write(JSON.stringify({
                        "status":"false",
                        "message":"欄位未填寫正確，或無此todo id"
                    }));
                    response.end();  
                }
                
            })
     //-----------------------------------------------------------------
  ```
  * postman POST 非JSON格式
  
    ![](https://hackmd.io/_uploads/SJ7hU6IzT.png)
    
**格式錯誤2. JSON 中 key值 錯誤**
> 必要欄位沒有 POST -> undefined 狀態

* #### STEP 11-3. 修改 try 區塊 : 若沒有回傳todo{"title":title}，印出錯誤資訊
    ```js=
      //POST方法-------------------------------------------------------
            }else if(request.url=='/todolist' && request.method == "POST"){

                request.on('end',()=>{
                    //try...catch------------------
                    try{             
                        const title = JSON.parse(body).title; 
                        console.log(title); //沒有title屬性的話 會印出undefined

                        //1. POST物件中有title屬性------------------------------------------
                        if(title !== undefined){  
                            const todo = {
                                "title":title, 
                                "id":uuidv4()
                            }
                            todos.push(todo);

                            response.writeHead(200,headers); 
                            response.write(JSON.stringify({
                                "status":"success",
                                data:todos,  
                            }));
                            response.end();  //回傳結束

                        //2. POST物件中沒有title屬性資料 -> undefined---------------------
                        }else{ 
                            //執行與catch error一樣的錯誤訊息
                            response.writeHead(400,headers); //400 bad request 錯誤請求 (格式錯誤)
                            response.write(JSON.stringify({
                                "status":"false",
                                "message":"欄位未填寫正確，或無此todo id"
                            }));
                            response.end();  
                        }

                    }catch(error){ 
                        response.writeHead(400,headers); //400 bad request 錯誤請求 (格式錯誤)
                        response.write(JSON.stringify({
                            "status":"false",
                            "message":"欄位未填寫正確，或無此todo id"
                        }));
                        response.end();  
                    }

                })
         //-----------------------------------------------------------------
    ```
  * postman 測試錯誤樣態2
     * POST 物件中沒有"title"屬性資料，仍會是 200 ok 回傳成功 (下圖 postman 回傳成功)
   
        | 修改前: 使用POST方法 (try區塊沒使用 if...else 執行必要欄位檢驗)|
        | -------- | 
        | ![](https://hackmd.io/_uploads/HyuwsTLM6.png)   | 
    * 將錯誤代碼使用 if...else 寫在 try 區塊 ( 如 **step 11-3.** )
            
        |修改後: 使用POST方法 (try區塊將必要屬性放在if執行內容，else 錯誤資訊回傳) |
        | -------- | 
        | ![](https://hackmd.io/_uploads/ByO92T8f6.png)   | 
     
<br>
        
## 12. 重構程式碼
> 整理重複的程式碼，將程式碼"模組化"

* #### STEP 12-1. 新增 errorHandle.js 檔案，放執行錯誤模組
    ```js=
    //此函式內容包含引用headers、response，因此需要引入相關變數或引數

    function errorHandle(response){

        const headers = {
            'Access-Control-Allow-Headers': 'Content-Type, Authorization, Content-Length, X-Requested-With',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'PATCH, POST, GET,OPTIONS,DELETE',
            'Content-Type': 'application/json'
        };

        response.writeHead(400,headers);
        response.write(JSON.stringify({
            "status":"false",
            "message":"欄位未填寫正確，或無此todo id"
        }))
        response.end();
    }

    //匯出module
    module.exports = errorHandle;
    ```
* #### STEP 12-2. 引用模組
  ```js=
  const errorHandle = require('./errorHandle'); //錯誤樣態執行程式
  
  //抽換程式碼--------------------------
  //POST 新增資料
    }else if(request.url=='/todolist' && request.method == "POST"){
        request.on('end',()=>{

            try{  
                const title = JSON.parse(body).title; 
                console.log(title); 

                if(title !== undefined){  
                    const todo = {
                        "title":title, 
                        "id":uuidv4()
                    }
                    todos.push(todo);
                    
                    response.writeHead(200,headers);
                    response.write(JSON.stringify({
                        "status":"success",
                        data:todos,   
                    }));
                    response.end();
            //使用自訂模組--------------------------------------
                }else{ 
                    errorHandle(response); 
                }
    
            }catch(error){ 
                errorHandle(response); 
            }
            //------------------------------------------------
                
        })
  //----------------------------------------------------
  
 
  ```


<br>

> [**Todolist RESTful API : 開發新刪修查的API (實作4) - CRUD ( DELETE API )**](https://hackmd.io/6w2zSZFkRR6G7AUTwEJ4nQ?view)