點燈坊

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

使用 Future 以 Polling 持續呼叫 API

Sam Xiao's Avatar 2021-05-29

有些資料會不斷變動,實務上會要求以 Polling 方式不斷呼叫 API 回傳資料。

Version

Vue 3.0.11
Fluture 14.0.0

Future

polling000

每秒鐘呼叫一次 API 取得資料。

api/getBooks_.js

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

export default () => attemptP(() => axios.get('/books'))

使用 attemptP() 將 Promise 轉成 Future。

<template lang='pug'>
ul
  li(v-for='x in books') {{ x.title }} / {{ x.price }}
</template>

<script setup>
import { ref, onUnmounted } from 'vue'
import { write } from 'vue3-fp'
import { pipe, map, prop, path } from 'ramda'
import { fork, mapRej } from 'fluture'
import getBooks from '/src/api/getBooks_'

let books = ref([])
let pollingId = 0

!(function f() {
  let polling = () => pollingId = setTimeout(f, 1000)
  
  pipe(
    getBooks,
    map(prop('data')),
    map(write(books)),
    mapRej(path(['response', 'data', 'error'])),
    fork(polling)(polling),
  )()
})()

onUnmounted(() => clearTimeout(pollingId))
</script>

16 行

!(function f() {
  let polling = () => pollingId = setTimeout(f, 1000)
  
  pipe(
    getBooks,
    map(prop('data')),
    map(write(books)),
    mapRej(path(['response', 'data', 'error'])),
    fork(polling)(polling),
  )()
})()

使用 Named IIFE 持續呼叫 API:

  • getBooks:呼叫 API 回傳 Future
  • map(prop('data')):在 Resolved Future 內取得 data
  • map(write(books)):在 Resolved Future 內寫入 books state
  • mapRej(path(['response', 'data', 'error'])):在 Rejected Future 內取得 response.date.error
  • fork(polling)(polling):無論 Rejected Future 或 Resolved Future 都繼續呼叫 API

Conclusion

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

Reference

Fluture, attemptP()
Fluture, mapRej()