實務上常遇到須先呼叫第一個 API 取得 id
後,才能以該 id
呼叫第二個 API 取得資料,這種相依性的 API 該如何處理呢 ?
Version
Vue 3.0.11
Composition API
按下 Get Category
會先呼叫 getBook()
取得 categoryId
,再將 categoryId
傳入 getCategory()
取得 category
。
<template lang='pug'>
div
button(@click='onClick') Get Category
div {{ category }}
</template>
<script setup>
import getBook from './api/getBook'
import getCategory from './api/getCategory'
ref: category = ''
let onClick = () => {
getBook(1)
.then(x => x.data.id)
.then(x => getCategory(x))
.then(x => x.data.category)
.then(x => category = x)
.catch(e => console.error(e))
}
</script>
13 行
let onClick = () => {
getBook(1)
.then(x => x.data.id)
.then(x => getCategory(x))
.then(x => x.data.category)
.then(x => category = x)
.catch(e => console.error(e))
}
getBook(1)
:呼叫getBook()
取得categoryId
then(x => x.data.id)
:getBook()
回傳為 Promise,在 Promise 內從data.id
取得categoryId
then(x => getCategory(x))
:呼叫getCategory()
取得category
then(x => x.data.category)
:在 Promise 內從data.category
取得category
then(x => category = x)
:在 Promise 內將category
寫入category
statecatch(e => console.error(e))
:顯示 error response
Point-free
結果不變,但使用 Point-free 改寫。
<template lang='pug'>
div
button(@click='onClick') Get Category
div {{ category }}
</template>
<script setup>
import { ref } from 'vue'
import { write } from 'vue3-fp'
import { pipe, thunkify, andThen as then, path, otherwise } from 'ramda'
import { error } from 'wink-fp'
import getBook from './api/getBook'
import getCategory from './api/getCategory'
let category = ref('')
let onClick = pipe(
thunkify(getBook)(1),
then(path(['data', 'id'])),
then(getCategory),
then(path(['data', 'category'])),
then(write(category)),
otherwise(error)
)
</script>
17 行
let onClick = pipe(
thunkify(getBook)(1),
then(path(['data', 'id'])),
then(getCategory),
then(path(['data', 'category'])),
then(write(category)),
otherwise(error)
)
thunkify(getBook)(1)
:將getBook()
轉成 Thunk 再傳入資料then(path(['data', 'id']))
:getBook()
回傳為 Promise,在 Promise 內從data.id
取得categoryId
then(getCategory)
:呼叫getCategory()
取得category
then(path(['data', 'category']))
:在 Promise 內從data.category
取得category
then(write(category))
:在 Promise 內將category
寫入category
stateotherwise(error)
:顯示 error response
pipe()
結果不變,但使用 pipe()
抽出 function。
<template lang='pug'>
div
button(@click='onClick') Get Category
div {{ category }}
</template>
<script setup>
import { ref } from 'vue'
import { write } from 'vue3-fp'
import { pipe, thunkify, andThen as then, path, otherwise } from 'ramda'
import { error } from 'wink-fp'
import getBook from './api/getBook'
import getCategory from './api/getCategory'
let category = ref('')
let getData = pipe(
getBook,
then(path(['data', 'id'])),
then(getCategory),
then(path(['data', 'category'])),
)
let onClick = pipe(
thunkify(getData)(1),
then(write(category)),
otherwise(error)
)
</script>
17 行
let getData = pipe(
getBook,
then(path(['data', 'id'])),
then(getCategory),
then(path(['data', 'category'])),
)
將 getBook()
與 getCategory()
抽成 getData()
。
由於 getBook()
回傳 Promise,因此後續的 function 都在 then()
內。
24 行
let onClick = pipe(
thunkify(getData)(1),
then(write(category)),
otherwise(error)
)
在 onClick()
內只需呼叫 getData()
即可。
pipeP()
結果不變,但使用 pipeP()
抽出 function。
<template lang='pug'>
div
button(@click='onClick') Get Category
div {{ category }}
</template>
<script setup>
import { ref } from 'vue'
import { write } from 'vue3-fp'
import { pipe, thunkify, andThen as then, path, otherwise } from 'ramda'
import { pipeP, error } from 'wink-fp'
import getBook from './api/getBook'
import getCategory from './api/getCategory'
let category = ref('')
let getData = pipeP(
getBook,
path(['data', 'id']),
getCategory,
path(['data', 'category'])
)
let onClick = pipe(
thunkify(getData)(1),
then(write(category)),
otherwise(error)
)
</script>
17 行
let getData = pipeP(
getBook,
path(['data', 'id']),
getCategory,
path(['data', 'category'])
)
getData()
功能不變,但改用 pipeP()
組合。
pipeP()
可直接組合 synchronous function 與 asynchronous function,儘管回傳 Promise,也不用將 function 包在 then()
內,因此寫起來較 pipe()
精簡。
Conclusion
pipeP()
的P
即表示 Promise,可直接在 Promise 之後組合 synchronous function 與 asynchronous function 而不需在then()
內