點燈坊

失くすものさえない今が強くなるチャンスよ

使用 Promise 處理 GET 回傳 Primitive

Sam Xiao's Avatar 2021-05-19

處理 RESTful API 的 GET 回傳 Primitive 在實務上一定會碰到,由於 Composition API 沒有使用 this,在 Vue 3 將有不同處理方式。

Version

Vue 3.0.11

Composition API

get000

按下 Get Book 會從 API 獲得 title

api/getBook.js

import axios from 'axios'

export default id => axios.get(`/book/${id}`)

使用 axios.get 回傳 Promise。

App.vue

<template lang='pug'>
div
  button(@click='onClick') Get Book
div {{ title }}
</template>

<script setup>
import getBook from '/src/api/getBook'

ref: title = ''

let onClick = () => {
  getBook(1)
    .then(x => x.data)
    .then(x => title = x.title)
    .catch(e => console.error (e.response.data.error))
}
</script>

第 8 行

import getBook from '/src/api/getBook'

引用 API function 從 API 取得 data。

10 行

ref: title = ''

使用 ref sugar 定義 title state 較適合 Composition API。

12 行

let onClick = () => {
  getBook(1)
    .then(x => x.data)
    .then(x => title = x.title)
    .catch(e => console.error (e.response.data.error))
}

由於 getBook 回傳 Promise,因此使用 then() 寫入 side effect。

由於不必透過 this 讀取 title state,因此 onClick() 可安心使用 arrow function,不必再使用 function expression。

Point-free

get000

結果不變,但使用 Point-free 改寫。

api/getBook.js

import axios from 'axios'

export default id => _ => axios.get(`/book/${id}`)

使用 axios.get 回傳 Promise。

App.vue

<template lang='pug'>
div
  button(@click='onClick') Get Book
div {{ title }}
</template>

<script setup>
import { ref } from 'vue'
import { write } from 'vue3-fp'
import { pipe, andThen as then, path, otherwise } from 'ramda'
import { error } from 'wink-fp'
import getBook from '/src/api/getBook'

let title = ref ('')

let errorHandling = pipe (
  path (['response', 'data', 'error']), 
  error
)

let onClick = pipe (
  getBook (1),
  then (path (['data', 'title'])),
  then (write (title)),
  otherwise (errorHandling)
)
</script>

14 行

let title = ref ('')

使用 ref 定義 title state 較適合 Point-free。

21 行

let onClick = pipe (
  getBook (1),
  then (path (['data', 'title'])),
  then (write (title)),
  otherwise (errorHandling)
)

使用 pipe 組合 onClick

  • getBook (1):將 id 傳入 getBook 回傳 Promise
  • then (path (['data', 'title'])):在 Resolved Promise 內取出 data.title
  • then (write (title)):在 Resolved Promise 內寫入 title state
  • otherwise (errorHandling):傳入 errorHandling 處理 Rejected Promise

16 行

let errorHandling = pipe (
  path (['response', 'data', 'error']), 
  error
)

使用 pipe 組合 errorHandling

  • path (['response', 'data', 'error']):在 Rejected Promise 內取出 response.data.error
  • error:印出錯誤訊息

Conclusion

  • Vue 3 Composition API 由於沒有使用 this,使得 Point-free 成為可能,event handler 都可以直接以 pure function 組合出來