redux-saga学习笔记

官方文档:https://redux-saga.js.org/

saga

saga解释
redux-sagaredux 的一个异步处理工具

相同的工具还有 redux-thunk

相比之下我觉得 redux-thunk 的上手难度比较低,redux-saga 本身的 generator 特性使异步的处理更加地优雅


组织方式

在一个 saga 内部
saga内部组织


saga 宏观布局
saga宏观布局


宏观布局

saga宏观布局

某saga (事件)

// worker saga
function* loginHandle(action) {
  try {
    // 两个顺序异步请求
    const res1 = yield call(LoginService.login, action.payload);
    const res2 = yield call(LoginService.getMoreUserInfo, res1);
    // 状态更新
    yield put({type: LOGIN_SUCCESS, payload: res2});
  } catch (err) {
    yield put({type: LOGIN_FAILURE, payload: err});
  }
}

// watcher saga
function* loginSaga() {
  yield takeEvery(LOGIN_SAGA, loginHandle);
}

export default loginSaga;

事件总线

import {all} from "redux-saga/effects";
import loginSaga from "./loginSaga";

export default function* rootSaga() {
  yield all([loginSaga()]);
}

Store

import {loginReducer} from "./loginReducer";
import {createStore, combineReducers, applyMiddleware} from "redux";
import createSagaMiddleware from "redux-saga";
import rootSaga from "../action/rootSaga";

// step1. 创建saga中间件
const sagaMiddleware = createSagaMiddleware();

const store = createStore(
  combineReducers({user: loginReducer}),
	
  // step2. 在创建的商店中应用
  applyMiddleware(sagaMiddleware)
);

// step3. 开始监听事件总线
sagaMiddleware.run(rootSaga);

export default store;


微观布局

saga微观布局

以下 API 均从 redux-saga/effects 导入

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

监听

  • takeEvery(类型,回调)
  • takeLatest(类型,回调)
    最后一次执行会终止上一次执行,和防抖类似
  • take(类型,回调)
    只执行一次

eg.

// watcher saga
function* loginSaga() {
  yield takeEvery(LOGIN_SAGA, loginHandle);
}

export default loginSaga;

// 1.此处的 LOGIN_SAGA 就是 reducer 的 type 
// 2.对于需要用 saga 处理的 reducer,
//   监听的地方和传统的 reducer不同,
//   saga 监听的对象单独拎出来放在以上API的第一个参数

用其他 API 实现 takeEvery

const takeEvery = (pattern, saga, ...args) =>
  call(function*() {
    while (true) {
      const action = yield take(pattern);
      yield fork(saga, ...args.concat(action));
    }
});

执行

  • call
    yield call([obj, obj.method], arg1, arg2, …)
    const products = yield call(Api.fetch, '/products')
  • fork
    用法和 call 类似,只是 fork 是非阻塞,而 call 是阻塞的
    意思是如果某次 call 需要用到上一次的值,那就不能用 fork
  • apply
    yield apply(obj, obj.method, [arg1, arg2, …])
  • cps
    用于处理组件回调 (这个地方官方没有给出实际例子,笔者目前也没有遇到过这样的场景,暂时举不出例子)

eg.

// worker saga
function* loginHandle(action) {
  try {
    // 两个顺序异步请求
    const res1 = yield call(LoginService.login, action.payload);
    const res2 = yield call(LoginService.getMoreUserInfo, res1);
    // 状态更新
    yield put({type: LOGIN_SUCCESS, payload: res2});
  } catch (err) {
    yield put({type: LOGIN_FAILURE, payload: err});
  }
}

派发

一、worker saga的参数

function* fetchProducts (dispatch) {
  const products = yield call(Api.fetch, '/products');
  dispatch({type: 'XXX', products});
}

注意:官方并不推荐在生成器内部调用函数这种用法


二、put

function* fetchProducts () {
  const products = yield call(Api.fetch, '/products');
  yield put({type: 'XXX', products});
}

感谢你能看到这里~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值