這幾天在複習後端和製作RESTful API,想用解構的方式把 req.body
拆成變數,再用mongoose傳入mongoDB更新資料。
例如我預期可以接收到API參數有 id, name, age, major, merit, other,所以寫了一個解構語法拆解 req.body 物件 const {id, name, age, major, merit, other} = req.body;
。
假設使用者只在 name 和 age 輸入參數值,結果發現在沒有給定屬性預設值的情況下,即使解構時特別指定變數名稱,沒對應到物件屬性就不會被解構出來。
換句話說JS的解構語法,只會解構出有屬性存在的變數,因此上述解構出來的變數只存在 name
和 age
。
會造成什麼樣的問題?
我在連結資料庫更新資料的方式是,傳入 id
去查找。
如果使用者沒輸入 id
,在用 mongoose 的 findOneAndUpdate() 因為不會輸入查詢值,就會直接跳出查詢,而且我也不會收到錯誤😅
為了避免沒有輸入 id
,我這邊是給定 id=null
(下圖),因為 mongoose 的 Schema 有設定 id:{required: true}
,在更新資料那邊會偵測 id 是否為 null,若沒有就會給錯誤訊息,所以我就可以用 res.send(error)
偷懶地把 mongoose 錯誤訊息傳回去給使用API的人。
目前的解決辦法?
目前想到兩種解決辦法。
第一個是:先把每個解構的變數都給定預設值,強迫每個變數在解構沒有取得變數值的情況下,確保有這個變數且值為 null
,例如:
const {
id = null
, name = null
, age = null
, major = null
, merit = null
, other = null
} = req.body;
並且在查找前就要判斷 id === null
,不過這邊就是不想加入自訂錯誤訊息的偷懶作法,之後有修正更正確的版本再回來更新圖片。
(2022.05.26 Updated)
第二種作法是先確認 req.body
是否擁有所有需要更新的屬性資料,我這邊的作法是用 Array 的 every
method 去確認 req.body 是否有同名的key。確認無誤才把 req.body
拿去更新資料庫。
const properties = ["id", "name", "age", "major", "merit", "other"];
if(properties.every(p => p in req.body){
res.status(400)
.send({
"Error": "Please update all the property value of this data"
})
} else{
// destructuring req.body and put the data into database
}
後記:
速看了一下MDN好像也沒特別說這件事, 還是這是常識? 總之先記錄一下這個發現。
References