點燈坊

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

使用 Future 處理 Post

Sam Xiao's Avatar 2021-05-29

實務上常遇到 API 需要以 POST 以 Body 傳入,傳統會使用 Promise 處理,事實上 Future 更適合 Point-free。

Version

Vue 3.0.11
Fluture 14.0.0

Future

post000

按下 Submit 後會將 IDPassword 以 POST 傳入資料。

api/login_.js

import axios from 'axios'
import { attemptP } from 'fluture'

export default body => attemptP (() => axios.post('/login', body))
  • attemptP:將回傳 Promise 的 function 轉成 Future

App.vue

<template lang='pug'>
div
  span ID
  input(v-model='id')
div
  span Password
  input(v-model='password', type='password')
div
  button(@click='onClick') Submit
div {{ result.id }}
div {{ result.password }}
</template>

<script setup>
import { ref, unref } from 'vue'
import { write } from 'vue3-fp'
import { pipe, map, prop, path, zipObj } from 'ramda'
import { error } from 'wink-fp'
import { fork, mapRej } from 'fluture'
import login from '/src/api/login_'

let id = ref ('')
let password = ref ('')
let result = ref ({})

let onClick = pipe (
  () => [unref (id), unref (password)],
  zipObj (['id', 'password']),
  login,
  map (prop ('data')),
  mapRej (path (['response', 'data', 'error'])),
  fork (error) (write (result))
)
</script>

26 行

let onClick = pipe (
  () => [unref (id), unref (password)],
  zipObj (['id', 'password']),
  login,
  map (prop ('data')),
  mapRej (path (['response', 'data', 'error'])),
  fork (error) (write (result))
)

使用 pipe 組合 onClick

  • () => [unref(id), unref(password)]:使用 unref() 讀取 state 並以 Array 回傳,這裡不能使用 K combinator,Vue 3 會失去 reactivity
  • zipObj (['id', 'password']):組合出 Object 準備傳入 login
  • login:呼叫 API function 回傳 Future
  • map (prop ('data')):在 Resolved Future 內取得 data
  • mapRej (path (['response', 'data', 'error'])):在 Rejected Future 內取得 response.date.error
  • fork (error) (write(result)):從 Future 內處理 Rejected Future,並從 Resolved Future 內取出資料寫入 result state

Conclusion

  • 透過 mapRef 可在 pipe 內處理 Rejected Future,不必再如 otherwise 需另外組合 function 處理

Reference

Fluture, attemptP
Fluture, mapRej