Promise 很像 Monad 但又不是 Monad,Monad 應該統一使用 map
與 chain
,但 Promise 卻使用自己的 then
,而 Future 則符合 Fantasy Land 規格,用法與觀念也與 Maybe 與 Either 相同。
Version
Vue 3.0.11
Fluture 14.0.0
Future
按下 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,可使用encaseP
將axios.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
回傳 Futuremap (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