為了模擬一些前端可能遇到的 issue,
我試著在 API 寫了一點手腳,
但我先不說我在 API 寫了什麼,
就跟著我的腳步一起來看看到底發生什麼問題,
最後又發現是誰的問題呢?
這邊先前情提要一下檔案架構:
紅框處就是我們今天比較會接觸到的檔案~
(PS. 這個架構應該沒有很正確,但就是測試用,所以就請不要太介意XD)
開始前也先記得打開前後端:
後端:node server.js
前端:npm start
今天鐵人餐廳的員工小鐵一如既往的在餐廳打烊後要在後台 key 今日的銷售數量,
正常輸入完品項跟數量後卻出現以下問題:
出現錯誤訊息,而且只說是 未知的錯誤
,
於是小鐵報案給工程師,
因為這是系統畫面出的錯誤,
所以前端工程師小前會先收到這個報案。
小前第一步就先看看後端有沒有問題,
看起來查詢資料沒有問題,
於是接著小前模擬小鐵的動作,
發現也會出現一樣的錯誤訊息。
「那輸入其它的值看看會不會有問題吧!」
於是小前把 臭豆腐
改成 香豆腐
再試一次:
小前發現他改成 香豆腐
call API 就成功了,
那再輸入一次 香豆腐
呢?
哦?這次也遇到一樣的錯誤了,
於是他決定在 app.js
(前端的 code) 埋一下 console.log
來看 API 回了什麼。
.catch(function (e) {
console.log(e); // 多了這行
let err;
switch(e?.response?.status) {
case 403:
err = '您沒有新增的權限,請確認後再試。';
break;
default:
err = '未知的錯誤';
}
... (略)
});
他發現 API 回了 409
,
可是沒有更詳細的資訊,
他還是不知其所以然,難道要來通靈了嗎
還是直接報案給後端?
不,等等,小前發現他知道 API 的 code 在哪裡,
於是小前決定打開 server.js
一探究竟。
第一步打開 server.js
,
直接搜尋 409
看看吧!
果不其然馬上找到關鍵處,
就是這段:
server.use((req, res, next) => {
if (req.method === 'POST') {
const sales = readSales();
const sale = sales.filter(s => s.item === req.body.item)[0];
if (sale === undefined || sale === null) {
next();
} else {
res.sendStatus(409);
}
} else {
next()
}
})
首先會去判斷 sale === undefined || sale === null
,
不是的話才會執行 res.sendStatus(409)
,
那 sale
又是什麼?
往上一行追:
const sale = sales.filter(s => s.item === req.body.item)[0];
是從 sales.filter
而來,
那 sales
又是什麼呢?
再繼續往上追:
const sales = readSales();
那 readSales
又是啥咪?
搜尋一下 readSales
可以找到這段:
function readSales() {
const dbRaw = fs.readFileSync('./db.json');
const sales = JSON.parse(dbRaw).sales;
return sales;
}
看起來是去找 db.json
裡面的 sales
存起來成 sales
,
那我們再回去看這兩行:
const sales = readSales();
const sale = sales.filter(s => s.item === req.body.item)[0];
所以這兩行意思就是,
比對 db.json
裡 sales
的資料,
一筆一筆去跟 req.body
去比對 item,
(PS. req
就是指 request,也就是前端發給 API 的要求,
所以 req.body
就是指 request 的內容。)
const sales = readSales();
const sale = sales.filter(s => s.item === req.body.item)[0];
if (sale === undefined || sale === null) {
next();
} else {
res.sendStatus(409);
}
這幾行再一起看,sales
比對不到就會繼續做,
比對到已經存在就要拋出 409
的 HTTP 狀態碼。
哦!事情到這裡已經明朗了,
也就是說 臭豆腐
這筆資料已經存在了是嗎?
讓我們來檢查看看:http://localhost:10000/sales
BINGO!臭豆腐
已經存在所以無法成功新增,
小前就可以開心結案了...
不不不,
還差一步,
還記得之前的文章前端的 code 只有處理 403
的 HTTP 狀態碼嗎?
switch(e?.response?.status) {
case 403:
err = '您沒有新增的權限,請確認後再試。';
break;
default:
err = '未知的錯誤';
}
所以除了 403 以外的錯誤都會顯示 未知的錯誤
,
這也是導致使用者小鐵不知道發生什麼事只能報案給工程師的主因,
這時候小前就要把 409
的情況也加進來,
像這樣:
switch(e?.response?.status) {
case 403:
err = '您沒有新增的權限,請確認後再試。';
break;
case 409:
err = '此項目已存在,請確認輸入的資料是否有誤。';
break;
default:
err = '未知的錯誤';
}
然後也同步來確認看看錯誤訊息有沒有成功顯示吧!
沒錯,事情到這裡就算圓滿結束了,
小前可以跟小鐵說是因為資料已經存在,
而下次如果再輸入相同的資料,
就會顯示 此項目已存在
,
小鐵就會知道是自己輸入了重複的資料,
從此小鐵再也不會報案了,
小前從此過著幸福快樂的日子...
... 最好是啦!
(To Be Continued...)
console.log
看 API 有沒有詳細訊息HTTP 409 Conflict 表示請求與伺服器目前狀態衝突
衝突通常發生於 PUT (en-US) 請求。如上傳一個已經有舊版本存在於伺服器的檔案而導致版本控制衝突時,會回復一個 409 錯誤。
Conflict
字面上來看其實就是衝突的意思,
所以我們看到 409
就大概會可以先猜是因為資料重複或其它狀況導致的衝突問題。
4 - Add JSON server
=> 感謝大大詳細文章orz 因為老實說 JSON Server 的官方文件不算寫得很詳細XD
(我猜可能是要給本來就是在寫 API 的開發者看的吧orz)
這幾天文章終於來到有趣的報案系列XD
不過說實話,後端在寫 API 時就會把出錯的各種情況寫好,
提醒前端要在前端頁面加上這些錯誤訊息提醒視窗,
但我初期在寫前端時,
因為不知道這些眉角,
所以也算是因為這樣多學怎麼看後端的 code。
然後因為要自己模擬 API 錯誤,
網路有提供 call 的 API 又沒辦法這麼客製化,
所以只好自己捲起袖子寫 API 了XD
不過我寫的都很簡單啦orz
我知道離真正的後端還有很長一段路orz