實務上有時必須對兩個以上 Table 做 Query,將結果合併後再傳回,由於 Knex 回傳為 Promise,該如何將這兩個 Promise 合併呢 ?
Version
Knex 0.20.3
Async Await
let f = async _ => {
let books1 = await mySQL ('books').where ('price', '>', 200)
let books2 = await mySQL ('books').where ('price', '<=', 200)
return books1.concat (books2)
}
由於 Knex 回傳 Promise,若搭配 await
解構後成為 Array,因此可使用 Array.prototype.concat()
將兩個 Array 加以合併。
由於使用了 await
,因次 function 必須宣告為 async
再轉為 Promise。
Promise.all
let f = _ => {
let books1 = mySQL ('books').where ('price', '>', 200)
let books2 = mySQL ('books').where ('price', '<=', 200)
return Promise.all ([books1, books2]).then (flatten)
}
由於 Knex 回傳為 Promise,至於這兩個 Promise 誰先完成很難說,要視資料量與網路速度決定,因此使用了 Promise.all
等兩個 Promise 都完成後才合併,算是 asynchronous 版本的 Array.prototype.concat()
。
不過 Promise.all
的結果為兩層 Array,因此還必須透過 Ramda 的 flatten
打平後才是我們要的結果。
Conclusion
- 由本文可發現 Promise 在 ECMAScript 有兩種處理方式,
await
會將值從 Promise 轉為正常值,就可繼續使用 imperative 寫法,最後再使用async
回傳 Promise;而Promise
系列方法則透過then
提供 function 針對 Promise 內部資料處理,最後直接回傳 Promise,屬於 FP 風格 - 由於
then
要求傳入 function,可善用 Ramda 的 function 或自行組合 function 傳入