redux-saga学习笔记

redux-saga

redux的一个中间件,用于实现异步操作

原理

saga是由Generator函数实现的,(Generator函数能够实现将外部数据传入内部,同时将内部函数传递到外部,并能切换调用者,类似于lua中的协程。)我们自己编写Generator函数,Generator函数将会yield包含指令的稳步对象,redux-saga中间件将确保执行这些执行并将指令结果回馈到Generator,实现上述的参数内外互传。例如异步请求,Generator函数yield返回一个Promise对象,当Promise执行resolve后,将成功结果返回到Generator函数内部,继续向下执行。

核心API

recux与saga连接函数
  1. createSagaMiddleware

用于创建一个redux中间件,将saga于redux的store联系起来,例子见下方。

saga异步action捕捉函数

在同步redux中,当UI通过dispath发出action时,由reducer负责匹配并处理,同理,在saga中,上述两个函数用于捕捉指定action并执行对应的自定义的异步Generator函数

  1. takeEvery
  2. takeLast
  3. take

takeEvery用于捕捉每次action,而takeLast只捕捉并执行最新一次的action

例如:当点击商城某一分类名:单片机 获取对应商品列表时,每点击一次 “单片机”,就像后台获取一次对应分类下的列表。利用saga实现如下:

异步reducer

import { call, put } from "redux-saga/effects"
export function * getData(action){
    try{
        //像后台发出请求,执行到yield时将执行权移交到saga中间件,知道执行完毕,将结果返回到data中
        const data = yield call(Api.getList, action.url);
        //拿到结果后,发出aciton,通知UI变化
        yield put({type: "GET_SUCCESS",data})
    }
}

action捕捉

import { takeEvery } from "redux-saga"
function* watchAsynAction(){
    //捕捉每次dispath发出的“GET_GOODS_BY_TYPE”action,捕捉到一次,执行一次getData
    yield * takeEvery("GET_GOODS_BY_TYPE",getData)
}

以上两个代码片段一般出现在同一个sagas.js文件中

页面

import {createStore, applyMiddleware } from "redux"
import createSagaMiddleware from "redux-saga"

const sagamiddle = createSagaMiddleware();
const store = createStore({
    reducer,//同步reducer
    applyMiddleware(sagaMiddleware)
})
class index extends React.Component{
    ......
    render(){
       ...
       <button onClick={store.dispath({type:"GET_GOODS_BY_TYPE"})}>
       ...
    }
	...
}

takeLast与takeEvery功能相同,唯一区别是,takeLast只执行最新启动的异步操作,此前如果有未执行的则取消。

take用于监听现在未发生的aciton,阻塞中间件,知道对应action发生,配合fork能够实现类似takeEvery的效果

function* watchAsynAction(){
    while(true){
        yield take("GET_GOODS_BY_TYPE")
        yield fork(getData)
    }
}
saga异步调用函数(类似store.dispath方法)
  1. call (fn, …args)
  2. fork (fn, …args)
  3. select (selector, …args)

call和fork都是将fn的调用转移到saga中间件来执行,arg是中间件调用fn函数的参数,两者不同之处在于call是阻塞的,fork是非阻塞的。

saga获取状态函数
  1. select(selector, …args)

功能类似同步redux中的store.getState,用于获取store中的数据

官方简单例子

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from "redux-saga"
import Counter from './Counter'
import reducer from './reducers'
import rootSaga from "./sagas"


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

const store = createStore(
  reducer,
  applyMiddleware(sagaMiddleware)//createSagaMiddleware 工厂函数来创建一个 Saga middleware。
)


sagaMiddleware.run(rootSaga)

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

function render() {
  ReactDOM.render(
    <Counter
      value={store.getState()}
      onIncrement={() => action('INCREMENT')}
      onDecrement={() => action('DECREMENT')}
      onIncrementAsync={() => action('INCREMENT_ASYNC')} />,
    document.getElementById('root')
  )
}

render()
store.subscribe(render)

sagas.js

import { delay, takeEvery } from "redux-saga"
import { put, all, take, fork } from "redux-saga/effects"

export function* helloSaga() {
  console.log("hello Sagas");
}

// Our worker Saga :将执行异步的increment 任务
function* incrementAsync() {

  //delay是一个promise,延时参数值s后执行resolve,用于block(阻塞)Generator
  // Sagas 被实现为 Generator functions,它会 yield 对象到 redux-saga middleware。 
  //被 yield 的对象都是一类指令,指令可被 middleware 解释执行。当 middleware 取得一个 yield 后的 Promise,
  //middleware 会暂停 Saga,直到 Promise 完成。 
  //在下面的例子中,incrementAsync 这个 Saga 会暂停直到 delay 返回的 Promise 被 resolve,这个 Promise 将在 1 秒后 resolve。
  yield delay(1000)

  // put 就是我们称作 Effect 的一个例子。
  // Effects 是一些简单 Javascript 对象,包含了要被 middleware 执行的指令。 
  // 当 middleware 拿到一个被 Saga yield 的 Effect,它会暂停 Saga,直到 Effect 执行完成,然后 Saga 会再次被恢复。

  yield put({ type: "INCREMENT" })

}

//Our watcher Saga 在每个INCREMENT_ASYNC action spawn 一个新的incrementAsync 任务
function* watchIncrementAsync() {
  // yield takeEvery("INCREMENT_ASYNC", incrementAsync);

  //与上述 takeEvery 功能相同,疑问:fork何时结束???
  while (true) {
    yield take('INCREMENT_ASYNC');
    yield fork(incrementAsync);
  }

}

export default function* rootSaga() {
  yield all([
    helloSaga(),
    watchIncrementAsync()
  ])
}

reducers.js

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

最后 记录今天复习到的一个词语:陈力就列,不能者止 ,不能适应这个时代,就会被淘汰!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值