點燈坊

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

Fluture 初體驗

Sam Xiao's Avatar 2021-06-27

Promise 很像 Monad 但又不是 Monad,Monad 應該統一使用 mapchain,但 Promise 卻使用自己的 then,而 Future 則符合 Fantasy Land 規格,用法與觀念也與 Maybe 與 Either 相同。

Version

Vue 3.0.11
Fluture 14.0.0

Future

overview000

按下 Get Book 會從 API 獲得 title

api/getBook_.js

import axios from 'axios'
import { encaseP } from 'fluture'

export default id => _ => encaseP (axios.get) (`/book/${id}`)
  • encaseP:我們仍可繼續使用 Axios 呼叫 API,但 axios.get 回傳 Promise,可使用 encasePaxios.get 先轉成回傳 Future 的 function 後再傳入 url

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, map, path } from 'ramda'
import { error } from 'wink-fp'
import { fork, mapRej } from 'fluture'
import getBook from '/src/api/getBook_'

let title = ref ('')

let onClick = pipe (
  getBook (1),
  map (path (['data', 'title'])),
  mapRej (path (['response', 'data', 'error'])),
  fork (error) (write (title))
)
</script>

17 行

let onClick = pipe (
  getBook (1),
  map (path (['data', 'title'])),
  mapRej (path (['response', 'data', 'error'])),
  fork (error) (write (title))
)

使用 pipe 組合 onClick

  • getBook (1):將 id 傳入 getBook 回傳 Future
  • map (path (['data', 'title'])):在 Resolved Future 內取得 data.title,如同 Maybe 與 Either 一樣使用 map
  • mapRej (path (['response', 'data', 'error'])):在 Rejected Future 內取得 response.date.error,用法與 map 一樣,只是改成 mapRej
  • fork (error) (write (title)):最後處理 Rejected Future 與 Resolve Future,與 Maybe 的 maybe_ 和 Either 的 either 類似,都是傳入 function

Conclusion

  • Future 與 Maybe、Either 都是 Monad,因此可使用 Functor 的 map 與 Monad 的 chain,最後也必須使用 fork 才能從 Future 取出,這也與 Maybe 的 maybe_ 和 Either 的 either 類似,不像 Promise 是自成一格使用 then