redux-saga 異步流

前言

React的做用View層次的前端框架,天然少不了不少中間件(Redux Middleware)作數據處理, 而redux-saga就是其中之一,目前這個中間件在網上的資料仍是比較少,估計應用的不是很普遍,可是若是使用得當,將會事半功倍的效果,下面仔細介紹一個這個中間件的具體使用流程和應用場景。javascript

redux-saga簡介

Redux-saga是Redux的一箇中間件,主要集中處理react架構中的異步處理工做,被定義爲generator(ES6)的形式,採用監聽的形式進行工做。前端

redux-saga安裝

使用npm進行安裝:java

npm install --save redux-saga

或者使用yarn:react

yarn add redux-saga

redux-saga經常使用方法解釋

redux Effects

Effect 是一個 javascript 對象,能夠經過 yield 傳達給 sagaMiddleware 進行執行在, 若是咱們應用redux-saga,全部的 Effect 都必須被 yield 纔會執行。npm

舉個例子,咱們要改寫下面這行代碼:redux

yield fetch(url);

應用saga:api

yield call(fetch, url)

take

等待 dispatch 匹配某個 action 。promise

好比下面這個例子:前端框架

....
while (true) {
  yield take('CLICK_Action');
  yield fork(clickButtonSaga);
}
....

put

觸發某個action, 做用和dispatch相同:架構

yield put({ type: 'CLICK' });

具體的例子:

import { call, put } from 'redux-saga/effects'

export function* fetchData(action) {
   try {
      const data = yield call(Api.fetchUser, action.payload.url)
      yield put({type: "FETCH_SUCCEEDED", data})
   } catch (error) {
      yield put({type: "FETCH_FAILED", error})
   }
}

select

做用和 redux thunk 中的 getState 相同。一般會與reselect庫配合使用。

call

有阻塞地調用 saga 或者返回 promise 的函數,只在觸發某個動做。

takeEvery

循環監聽某個觸發動做,咱們一般會使用while循環替代。

import { takeEvery } from 'redux-saga/effects'

function* watchFetchData() {
  yield takeEvery('FETCH_REQUESTED', fetchData)
}

takeLatest

對於觸發多個action的時候,只執行最後一個,其餘的會自動取消。

import { takeLatest } from 'redux-saga/effects'

function* watchFetchData() {
  yield takeLatest('FETCH_REQUESTED', fetchData)
}

fork 和 cancel

一般fork 和 cancel配合使用, 實現非阻塞任務,take是阻塞狀態,也就是實現執行take時候,沒法向下繼續執行,fork是非阻塞的,一樣可使用cancel取消一個fork 任務。

function* authorize(user, password) {
  try {
    const token = yield call(Api.authorize, user, password)
    yield put({type: 'LOGIN_SUCCESS', token})
  } catch(error) {
    yield put({type: 'LOGIN_ERROR', error})
  }
}

function* loginFlow() {
  while(true) {
    const {user, password} = yield take('LOGIN_REQUEST')
    yield fork(authorize, user, password)
    yield take(['LOGOUT', 'LOGIN_ERROR'])
    yield call(Api.clearItem('token'))
  }
}

上面例子中,當執行

yield fork(authorize, user, password)

的同時,也執行了下面代碼,進行logout的監聽操做。

yield take(['LOGOUT', 'LOGIN_ERROR'])

redux-saga使用案例

引入saga:

import { call, put, take, select } from 'redux-saga/effects';

建立任務:

/**
 * Created by Richard on 1/11/17.
 */
import { call, put, take, select } from 'redux-saga/effects';
import { get, getWordUrl } from '../../utils/api';
import {successFetchData } from './WordAction';

export default function* wordFlow() {
    try {
         const data = yield call(get, getWordUrl());
         yield put(successFetchData(data));
    } catch (e){

    }
}

建立saga:

import { fork } from 'redux-saga/effects';
import wordFlow from './containers/word-view/WordSaga';

export default function* rootSaga() {
  yield [
    fork(wordFlow)
  ];
}

與redux中間件進行整合:

/**
 * Created by Richard on 12/29/16.
 */
import { applyMiddleware, createStore, compose } from 'redux';

import createSagaMiddleware from 'redux-saga';

import reducers from '../reducers';

import sagas from '../sagas';

//建立saga middleware
const sagaMiddleware = createSagaMiddleware();

const middlewares = compose(applyMiddleware(sagaMiddleware)autoRehydrate());

export default function configureStore() {
        const store = createStore(reducers, undefined, middlewares);
        //運行全部已經註冊的saga
        sagaMiddleware.run(sagas);
        return store;
}

下面就能夠正常監聽狀態了。

redux-saga的優點

傳統意義講,咱們不少業務邏輯要在action中處理,因此會致使action的處理比較混亂,難以維護,並且代碼量比較大,若是咱們應用redux-saga會很大程度上簡化代碼, redux-saga 自己也有良好的擴展性, 很是方便的處理各類複雜的異步問題

相關文章
相關標籤/搜索