iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0
Modern Web

前端技術研究系列 第 17

Redux Saga 基礎 Effect (下集)

  • 分享至 

  • xImage
  •  

Redux-Saga 基礎概念要結束啦~
就來看看他最後兩篇章節吧

Error handling

可以利用 try/catch中處理 API 錯誤,或是透過API回的response情況來使用if/else判斷

function* fetchProducts() {
  try {
    const products = yield call(Api.fetch, '/products')
    yield put({ type: 'PRODUCTS_RECEIVED', products })
  }
  catch(error) {
    yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
  }
}
function fetchProductsApi() {
  return Api.fetch('/products')
    .then(response => ({ response }))
    .catch(error => ({ error }))
}

function* fetchProducts() {
  const { response, error } = yield call(fetchProductsApi)
  if (response)
    yield put({ type: 'PRODUCTS_RECEIVED', products: response })
  else
    yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
}

其他情況:
onError hook
錯誤發生的最後手段,error跑到rootSaga時,整個saga就會被停下,這時就可以使用onError,通知用戶且終止程式。

Using Saga Helpers

saga的輔助函數(監控特定 Action)
keywords: takeEverytakeLatesttake

  1. takeEvery:每次觸發相同type 的 action 時都會執行 fetchData,是最常見的,它提供了類似 redux-thunk 的行為。
import { takeEvery } from 'redux-saga/effects'

function* fetchData() { ... }

export function* watchGetStores() {
  yield takeEvery (getStores.type, fetchData);
}
  • takeEvery多個引用
    saga時可以這樣引用,行為就會像fork生成的一樣(允許我們在後台啟動多個 saga的一個effect)
    import { takeEvery } from 'redux-saga/effects'
    
    // FETCH_USERS
    function* fetchUsers(action) { ... }
    
    // CREATE_USER
    function* createUser(action) { ... }
    
    // use them in parallel
    export default function* rootSaga() {
      yield takeEvery('FETCH_USERS', fetchUsers)
      yield takeEvery('CREATE_USER', createUser)
    }
    
  1. takeLatest:只想獲得最新請求的回覆(response),始終顯示最新版本的數據。多次觸發相同 type 的 action 時,會以最後一次的回應為準,在之前還未完成(如,pending)的 fetchData將會被取消。
import { all, call, put, takeEvery, takeLatest } from 'redux-saga/effects';

function* fetchData() { ... }

export function* watchGetStores() {
  yield takeLatest(getStores.type, fetchData);
}
  1. take:透過 take 可以持續監聽某一 action,並且從該 yield 的 function 可以取得 action 的 payload(下方pass)
    實際上 takeEvery和 takeLatest都是透過 take(Lower level API)這個方法所包出來的 higher level API。當我們使用 call時在 middleware 的地方會停住 Saga,直到 Promise 被 resolve;使用 take時類似,它會停住 saga 直到對應的 action 被 dispatch 後才繼續。
function* watchFetchData() {
  while (true) {
    const action = yield take('FETCH_REQUESTED');
    // 做原本 fetch Data 要執行的動作 ...
  }
}

留意這裡用的 while (true) { … } 的寫法,因為 watchFetchData 是一個 Generator function,透過 while (true) 的寫法可以讓這個 Generator function 不會進到 done: true 的情況,因此每次疊代時都會等待該 action 產生。

如果沒有加上 while (true) 這個 Generator function 產生的 iterator 將執行一輪後就結束了,如此將只會監聽到一次該 action 的發生,之後便無法持續監聽某一 action。

結語:
明天將會實際來介紹一遍實際coding 範例~


上一篇
Redux Saga 基礎 Effect (上集)
下一篇
Redux-Saga 基本實作
系列文
前端技術研究30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言