成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

redux-saga框架使用詳解及Demo教程

Nosee / 1436人閱讀

摘要:通過創(chuàng)建將所有的異步操作邏輯收集在一個(gè)地方集中處理,可以用來代替中間件。

redux-saga框架使用詳解及Demo教程

前面我們講解過redux框架和dva框架的基本使用,因?yàn)閐va框架中effects模塊設(shè)計(jì)到了redux-saga中的知識(shí)點(diǎn),可能有的同學(xué)們會(huì)用dva框架,但是對(duì)redux-saga又不是很熟悉,今天我們就來簡(jiǎn)單的講解下saga框架的主要API和如何配合redux框架使用

redux-saga 官方地址

http://leonshi.com/redux-saga-in-chinese/index.html

Demo運(yùn)行效果圖

todoList

CounterApp

示例Demo地址

redux-saga-Demo作者還是按照以前的風(fēng)格,提供了兩個(gè)不同的版本,簡(jiǎn)單的 CounterApp, 稍復(fù)雜的 TodoList

CounterApp

https://github.com/guangqiang-liu/redux-saga-counterApp

todoList

https://github.com/guangqiang-liu/redux-saga-todoListDemo

什么是redux-saga
redux-saga 是一個(gè)用于管理 Redux 應(yīng)用異步操作的中間件(又稱異步 action)。 redux-saga 通過創(chuàng)建 Sagas 將所有的異步操作邏輯收集在一個(gè)地方集中處理,可以用來代替 redux-thunk 中間件。

這意味著應(yīng)用的邏輯會(huì)存在兩個(gè)地方:

Reducers 負(fù)責(zé)處理 action 的 state 更新

Sagas 負(fù)責(zé)協(xié)調(diào)那些復(fù)雜或異步的操作

Sagas是通過Generator函數(shù)來創(chuàng)建的,如果有不熟悉 Generator函數(shù)使用的,請(qǐng)查看阮老師對(duì)Generator的介紹

Sagas 不同于thunks,thunks 是在action被創(chuàng)建時(shí)調(diào)用,而 Sagas只會(huì)在應(yīng)用啟動(dòng)時(shí)調(diào)用(但初始啟動(dòng)的 Sagas 可能會(huì)動(dòng)態(tài)調(diào)用其他 Sagas),Sagas 可以被看作是在后臺(tái)運(yùn)行的進(jìn)程,Sagas 監(jiān)聽發(fā)起的action,然后決定基于這個(gè) action來做什么:是發(fā)起一個(gè)異步調(diào)用(比如一個(gè) fetch 請(qǐng)求),還是發(fā)起其他的action到Store,甚至是調(diào)用其他的 Sagas

在 redux-saga 的世界里,所有的任務(wù)都通用 yield Effects 來完成(Effect 可以看作是 redux-saga 的任務(wù)單元)。Effects 都是簡(jiǎn)單的 Javascript 對(duì)象,包含了要被 Saga middleware 執(zhí)行的信息(打個(gè)比方,你可以看到 Redux action其實(shí)是一個(gè)個(gè)包含執(zhí)行信息的對(duì)象), redux-saga 為各項(xiàng)任務(wù)提供了各種Effect創(chuàng)建器,比如調(diào)用一個(gè)異步函數(shù),發(fā)起一個(gè)action到Store,啟動(dòng)一個(gè)后臺(tái)任務(wù)或者等待一個(gè)滿足某些條件的未來的 action

redux-saga框架核心API

一、Saga 輔助函數(shù)

redux-saga提供了一些輔助函數(shù),用來在一些特定的action 被發(fā)起到Store時(shí)派生任務(wù),下面我先來講解兩個(gè)輔助函數(shù):takeEvery takeLatest

takeEvery

例如:每次點(diǎn)擊 Fetch 按鈕時(shí),我們發(fā)起一個(gè) FETCH_REQUESTED 的 action。 我們想通過啟動(dòng)一個(gè)任務(wù)從服務(wù)器獲取一些數(shù)據(jù),來處理這個(gè)action

首先我們創(chuàng)建一個(gè)將執(zhí)行異步 action 的任務(wù):

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});
   }
}

然后在每次 FETCH_REQUESTED action 被發(fā)起時(shí)啟動(dòng)上面的任務(wù)

import { takeEvery } from "redux-saga"

function* watchFetchData() {

  yield* takeEvery("FETCH_REQUESTED", fetchData)
}

注意:上面的 takeEvery 函數(shù)可以使用下面的寫法替換

function* watchFetchData() {
  
   while(true){
     yield take("FETCH_REQUESTED");
     yield fork(fetchData);
   }
}

takeLatest

在上面的例子中,takeEvery 允許多個(gè) fetchData 實(shí)例同時(shí)啟動(dòng),在某個(gè)特定時(shí)刻,我們可以啟動(dòng)一個(gè)新的 fetchData 任務(wù), 盡管之前還有一個(gè)或多個(gè) fetchData 尚未結(jié)束

如果我們只想得到最新那個(gè)請(qǐng)求的響應(yīng)(例如,始終顯示最新版本的數(shù)據(jù)),我們可以使用 takeLatest 輔助函數(shù)

import { takeLatest } from "redux-saga"

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

和takeEvery不同,在任何時(shí)刻 takeLatest 只允許執(zhí)行一個(gè) fetchData 任務(wù),并且這個(gè)任務(wù)是最后被啟動(dòng)的那個(gè),如果之前已經(jīng)有一個(gè)任務(wù)在執(zhí)行,那之前的這個(gè)任務(wù)會(huì)自動(dòng)被取消

二、Effect Creators

redux-saga框架提供了很多創(chuàng)建effect的函數(shù),下面我們就來簡(jiǎn)單的介紹下開發(fā)中最常用的幾種

take(pattern)

put(action)

call(fn, ...args)

fork(fn, ...args)

select(selector, ...args)

take(pattern)

take函數(shù)可以理解為監(jiān)聽未來的action,它創(chuàng)建了一個(gè)命令對(duì)象,告訴middleware等待一個(gè)特定的action, Generator會(huì)暫停,直到一個(gè)與pattern匹配的action被發(fā)起,才會(huì)繼續(xù)執(zhí)行下面的語句,也就是說,take是一個(gè)阻塞的 effect

用法:

function* watchFetchData() {
   while(true) {
        // 監(jiān)聽一個(gè)type為 "FETCH_REQUESTED" 的action的執(zhí)行,直到等到這個(gè)Action被觸發(fā),才會(huì)接著執(zhí)行下面的 yield fork(fetchData)  語句
     yield take("FETCH_REQUESTED");
     yield fork(fetchData);
   }
}

put(action)

put函數(shù)是用來發(fā)送action的 effect,你可以簡(jiǎn)單的把它理解成為redux框架中的dispatch函數(shù),當(dāng)put一個(gè)action后,reducer中就會(huì)計(jì)算新的state并返回,注意: put 也是阻塞 effect

用法:

export function* toggleItemFlow() {
    let list = []
    // 發(fā)送一個(gè)type為 "UPDATE_DATA" 的Action,用來更新數(shù)據(jù),參數(shù)為 `data:list`
    yield put({
      type: actionTypes.UPDATE_DATA,
      data: list
    })
}

call(fn, ...args)

call函數(shù)你可以把它簡(jiǎn)單的理解為就是可以調(diào)用其他函數(shù)的函數(shù),它命令 middleware 來調(diào)用fn 函數(shù), args為函數(shù)的參數(shù),注意: fn 函數(shù)可以是一個(gè) Generator 函數(shù),也可以是一個(gè)返回 Promise 的普通函數(shù),call 函數(shù)也是阻塞 effect

用法:

export const delay = ms => new Promise(resolve => setTimeout(resolve, ms))

export function* removeItem() {
  try {
      // 這里call 函數(shù)就調(diào)用了 delay 函數(shù),delay 函數(shù)為一個(gè)返回promise 的函數(shù)
    return yield call(delay, 500)
  } catch (err) {
    yield put({type: actionTypes.ERROR})
  }
}

fork(fn, ...args)

fork 函數(shù)和 call 函數(shù)很像,都是用來調(diào)用其他函數(shù)的,但是fork函數(shù)是非阻塞函數(shù),也就是說,程序執(zhí)行完 yield fork(fn, args) 這一行代碼后,會(huì)立即接著執(zhí)行下一行代碼語句,而不會(huì)等待fn函數(shù)返回結(jié)果后,在執(zhí)行下面的語句

用法:

import { fork } from "redux-saga/effects"

export default function* rootSaga() {
  // 下面的四個(gè) Generator 函數(shù)會(huì)一次執(zhí)行,不會(huì)阻塞執(zhí)行
  yield fork(addItemFlow)
  yield fork(removeItemFlow)
  yield fork(toggleItemFlow)
  yield fork(modifyItem)
}

select(selector, ...args)

select 函數(shù)是用來指示 middleware調(diào)用提供的選擇器獲取Store上的state數(shù)據(jù),你也可以簡(jiǎn)單的把它理解為redux框架中獲取store上的 state數(shù)據(jù)一樣的功能 :store.getState()

用法:

export function* toggleItemFlow() {
     // 通過 select effect 來獲取 全局 state上的 `getTodoList` 中的 list
     let tempList = yield select(state => state.getTodoList.list)
}

三、createSagaMiddleware()

createSagaMiddleware 函數(shù)是用來創(chuàng)建一個(gè) Redux 中間件,將 Sagas 與 Redux Store 鏈接起來

sagas 中的每個(gè)函數(shù)都必須返回一個(gè) Generator 對(duì)象,middleware 會(huì)迭代這個(gè) Generator 并執(zhí)行所有 yield 后的 Effect(Effect 可以看作是 redux-saga 的任務(wù)單元)

用法:

import {createStore, applyMiddleware} from "redux"
import createSagaMiddleware from "redux-saga"
import reducers from "./reducers"
import rootSaga from "./rootSaga"

// 創(chuàng)建一個(gè)saga中間件
const sagaMiddleware = createSagaMiddleware()

// 創(chuàng)建store
const store = createStore(
  reducers,
  將sagaMiddleware 中間件傳入到 applyMiddleware 函數(shù)中
  applyMiddleware(sagaMiddleware)
)

// 動(dòng)態(tài)執(zhí)行saga,注意:run函數(shù)只能在store創(chuàng)建好之后調(diào)用
sagaMiddleware.run(rootSaga)

export default store

四、middleware.run(sagas, ...args)

動(dòng)態(tài)執(zhí)行sagas,用于applyMiddleware階段之后執(zhí)行sagas

sagas: Function: 一個(gè) Generator 函數(shù)

args: Array: 提供給 saga 的參數(shù) (除了 Store 的 getState 方法)

注意:動(dòng)態(tài)執(zhí)行saga語句 middleware.run(sagas) 必須要在store創(chuàng)建好之后才能執(zhí)行,在 store 之前執(zhí)行,程序會(huì)報(bào)錯(cuò)

以CounterApp Demo來看redux-saga具體使用方式

index.js

import React from "react";
import ReactDOM from "react-dom";
import {createStore, applyMiddleware} from "redux"
import createSagaMiddleware from "redux-saga"

import rootSaga from "./sagas"
import Counter from "./Counter"
import rootReducer from "./reducers"

const sagaMiddleware = createSagaMiddleware()
let middlewares = []
middlewares.push(sagaMiddleware)

const createStoreWithMiddleware = applyMiddleware(...middlewares)(createStore)
const store = createStoreWithMiddleware(rootReducer)

sagaMiddleware.run(rootSaga)

const action = type => store.dispatch({ type })

function render() {
  ReactDOM.render(
     action("INCREMENT")}
      onDecrement={() => action("DECREMENT")}
      onIncrementAsync={() => action("INCREMENT_ASYNC")} />,
    document.getElementById("root")
  )
}

render()

store.subscribe(render)

sagas.js

import { put, call, take,fork } from "redux-saga/effects";
import { takeEvery, takeLatest } from "redux-saga"

export const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

function* incrementAsync() {
  // 延遲 1s 在執(zhí)行 + 1操作
  yield call(delay, 1000);
  yield put({ type: "INCREMENT" });
}

export default function* rootSaga() {
  // while(true){
  //   yield take("INCREMENT_ASYNC");
  //   yield fork(incrementAsync);
  // }

  // 下面的寫法與上面的寫法上等效
  yield* takeEvery("INCREMENT_ASYNC", incrementAsync)
}

reducer.js

export default function counter(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1
    case "DECREMENT":
      return state - 1
    case "INCREMENT_ASYNC":
      return state
    default:
      return state
  }
}

從上面的代碼結(jié)構(gòu)可以看出,redux-saga的使用方式還是比較簡(jiǎn)單的,相比較之前的redux框架的CounterApp,多了一個(gè)sagas的文件,reducers文件還是之前的使用方式

總結(jié)

本文所講解的基本上是redux-saga框架在開發(fā)中最常使用到的常用API,還有很多不常用API,請(qǐng)參照redux-saga官方文檔:http://leonshi.com/redux-saga-in-chinese/docs/api/index.html

如果同學(xué)們看到文章這里,還是對(duì)redux-saga框架的基本使用不熟悉,概念模糊,建議看看作者提供的Demo示例

作者建議:同學(xué)們可以將作者之前講解的redux框架和redux-saga框架對(duì)比來學(xué)習(xí)理解,這樣更清楚他們之間的區(qū)別和聯(lián)系。

更多文章

作者React Native開源項(xiàng)目OneM【500+ star】地址(按照企業(yè)開發(fā)標(biāo)準(zhǔn)搭建框架完成開發(fā)的):https://github.com/guangqiang-liu/OneM:歡迎小伙伴們 star

作者簡(jiǎn)書主頁:包含60多篇RN開發(fā)相關(guān)的技術(shù)文章http://www.jianshu.com/u/023338566ca5 歡迎小伙伴們:多多關(guān)注,多多點(diǎn)贊

作者React Native QQ技術(shù)交流群:620792950 歡迎小伙伴進(jìn)群交流學(xué)習(xí)

友情提示:在開發(fā)中有遇到RN相關(guān)的技術(shù)問題,歡迎小伙伴加入交流群(620792950),在群里提問、互相交流學(xué)習(xí)。交流群也定期更新最新的RN學(xué)習(xí)資料給大家,謝謝大家支持!

小伙伴們掃下方二維碼加入RN技術(shù)交流QQ群

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97516.html

相關(guān)文章

  • dva框架使用詳解Demo教程

    摘要:框架的使用詳解及教程在前段時(shí)間,我們也學(xué)習(xí)講解過框架的基本使用,但是有很多同學(xué)在交流群里給我的反饋信息說,框架理解上有難度,看了之后還是一臉懵逼不知道如何下手,很多同學(xué)就轉(zhuǎn)向選擇使用框架。 dva框架的使用詳解及Demo教程 在前段時(shí)間,我們也學(xué)習(xí)講解過Redux框架的基本使用,但是有很多同學(xué)在交流群里給我的反饋信息說,redux框架理解上有難度,看了之后還是一臉懵逼不知道如何下手,很...

    bergwhite 評(píng)論0 收藏0
  • 前端資源系列(4)-前端學(xué)習(xí)資源分享&前端面試資源匯總

    摘要:特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請(qǐng)斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...

    princekin 評(píng)論0 收藏0
  • 2017-06-27 前端日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選漫談函數(shù)式編程一十年蹤跡的博客前端每周清單的優(yōu)勢(shì)與劣勢(shì)有望超越在嵌入式及物聯(lián)網(wǎng)的應(yīng)用現(xiàn)狀進(jìn)階系列高階組件詳解一前端之路譯如何充分利用控制臺(tái)掘金程序猿升級(jí)攻略眾成翻譯中文譯如何充分利用控制臺(tái)掘金前端從強(qiáng)制開啟壓縮探 2017-06-27 前端日?qǐng)?bào) 精選 漫談 JS 函數(shù)式編程(一) - 十年蹤跡的博客前端每周清單: Vue的優(yōu)勢(shì)與劣勢(shì);Node.js有望超越Java;JS在嵌...

    Eidesen 評(píng)論0 收藏0
  • React技術(shù)棧實(shí)現(xiàn)大眾點(diǎn)評(píng)Demo-初次使用redux-saga

    摘要:在的中,可以使用或者等來監(jiān)聽某個(gè),當(dāng)某個(gè)觸發(fā)后,可以使用等發(fā)起異步操作,操作完成后使用函數(shù)觸發(fā),同步更新,從而完成整個(gè)的更新。對(duì)于何時(shí)響應(yīng)和如何響應(yīng),并沒有控制權(quán)。的作用是用來取消一個(gè)還未返回的任務(wù)。 項(xiàng)目地址 項(xiàng)目截圖 showImg(https://segmentfault.com/img/bVUJwx?w=718&h=1294); redux-saga介紹 眾所周知,react僅...

    kel 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<