当前位置: 首页 > news >正文

国建设银行e路通网站申2023半夜免费b站推广

国建设银行e路通网站申,2023半夜免费b站推广,dede调用其他网站数据,贵阳有哪些做网站的公司redux-saga 官网:About | Redux-Saga 中文网:自述 Redux-Saga redux-saga 是一个用于管理 异步获取数据(副作用) 的redux中间件;它的目标是让副作用管理更容易,执行更高效,测试更简单,处理故障时更容易… …

redux-saga

官网:About | Redux-Saga
中文网:自述 · Redux-Saga


redux-saga 是一个用于管理 异步获取数据(副作用) 的redux中间件;它的目标是让副作用管理更容易,执行更高效,测试更简单,处理故障时更容易…

学习 redux-saga 之前,需要先掌握 ES6 中的 Iterator迭代器 和 Generator生成器 !!

1. redux-thunk与redux-saga的比较 

redux中的数据流
action ———> reducer ———> state

  • action是一个纯粹对象(plain object)
  • reducer是一个纯函数(和外界没有任何关系)
  • 都只能处理同步的操作

redux-thunk中间件的处理流程
action1 ———> middleware ———> action2 ———> reducer ———> state

/* redux-thunk中间件的部分源码 */
'use strict';
function createThunkMiddleware(extraArgument) {var middleware = function middleware(_ref) {var dispatch = _ref.dispatch,getState = _ref.getState;return function (next) {return function (action) {if (typeof action === 'function') {// 如果返回的action是个函数,则把函数执行「在函数中完成异步操作,用传递的dispatch单独实现派发!!」return action(dispatch, getState, extraArgument);}return next(action);};};};return middleware;
}

弊端:异步操作分散到每一个action中;而且返回函数中的代码具备多样性!!

redux-saga中间件的工作流程
redux-saga中提供了一系列的api,可以去监听纯粹对象格式的action,方便单元测试!!
action1 ———> redux-saga监听 ———> 执行提供的API方法 ———> 返回描述对象 ———> 执行异步操作 ———> action2 ———> reducer ———> state

这样说完,大家可能是不太理解的,那么接下来,我们去做一个案例,详细解读一下redux-saga的语法和优势!!

常用的中间件

  • redux-logger 输出派发日志(开发环境下)
  • redux-thunk / redux-promise 实现异步派发
  • redux-saga 实现异步派发的 管理的
  • redux-persist 实现公共状态持久化存储 [ 实施同步数据到 localStorage中;当页面刷新或者重新打开的时候,会把存储的信息放到 redux 容器中一份 ]

2. redux-saga的基础知识

备注:需要先准备一套基于 “redux、redux-thunk” 实现的投票案例,我们在此基础上去修改 !!

安装中间件
$ npm install redux-saga
$ yarn add redux-saga

使用中间件
store/index.js

  1. 创建 sagaMiddleware
  2. 插件中引入 sagaMiddleware
  3. 启动saga ( 需要创建一个saga文件 )
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import reducer from './reducer';
import saga from './saga';
// saga
const sagaMiddleware = createSagaMiddleware();
// 创建store容器
const store = createStore(reducer,applyMiddleware(sagaMiddleware)
);
// 启动saga
sagaMiddleware.run(saga);
export default store;

saga中间件原理:

 saga.js:

import {take, takeLatest, throttle, debounce,call, apply, fork, delay, put, select, all, cancel
} from 'redux-saga/effects';
import * as TYPES from './action-types';/* 工作区域 */
const workingCount = function* workingCount(action) {yield delay(2000);yield put({type: TYPES.DEMO_COUNT,payload: action.payload});
};
const workingSupport = function* workingSupport() {yield delay(1000);yield put({type: TYPES.VOTE_SUP});
};
const workingOppose = function* workingOppose() {yield delay(1000);yield put({type: TYPES.VOTE_OPP});
};/* 创建监听器,监听派发的异步任务 */
const saga = function* saga() {/* while (true) {let action = yield take(`${TYPES.DEMO_COUNT}@SAGA@`);yield fork(workingCount, action);yield fork(workingSupport, action);yield fork(workingOppose, action);} */yield takeLatest(`${TYPES.DEMO_COUNT}@SAGA@`, workingCount);yield takeLatest(`${TYPES.VOTE_SUP}@SAGA@`, workingSupport);yield takeLatest(`${TYPES.VOTE_OPP}@SAGA@`, workingOppose);
};
export default saga;

store/action-types.js

export const VOTE_SUP = "VOTE_SUP";
export const VOTE_OPP = "VOTE_OPP";export const DEMO = "DEMO";

 store/reducer

// demoReducer
import * as TYPES from '../action-types';
import _ from '../../assets/utils';
let initial = {num: 0
};
export default function demoReducer(state = initial, action) {state = _.clone(state);let { payload = 1 } = action;switch (action.type) {case TYPES.DEMO:state.num += payload;break;default:}return state;
};// index.js
import { combineReducers } from 'redux';
import voteReducer from './voteReducer';
import demoReducer from './demoReducer';
const reducer = combineReducers({vote: voteReducer,demo: demoReducer
});
export default reducer;

Demo.jsx组件中

import React from "react";
import { Button } from 'antd';
import { useSelector, useDispatch } from 'react-redux';
const Demo = function Demo() {const { num } = useSelector(state => state.demo),dispatch = useDispatch();return <div><span style={{ fontSize: 20, paddingLeft: 10 }}>{num}</span><br /><Button type="primary"onClick={() => {//基于dispatch进行派发....}}>按钮</Button></div>;
};
export default Demo;

 saga.js 工作流程

第一部分:创建监听器「基于saga的辅助函数」

  • take(pattern)

  • takeEvery(pattern, saga, …args)

  • takeLatest(pattern, saga, ..args)

  • throttle(ms, pattern, saga, ..args)

第二部分:创建执行函数「基于Effect创建器(API)」

  • put(action)

  • call(fn, …args)

  • fork(fn, …args)

  • select(selector, …args)

每一次组件派发后发生的事情
每一次在组件中,基于 dispatch(action) 的时候:

  • 首先会通知 reducer 执行

  • 然后再去通知 saga 中的监听器执行

 

 

关于监听器创建的细节
组件中

<Button type="primary"onClick={() => {dispatch({type: "DEMO-SAGA",payload: 10});}}>按钮
</Button>

 saga.js -> take 函数的运用

import * as TYPES from './action-types';
const working = function* working(action) {// 等价于 dispatch派发:通知reducer执行yield put({type: TYPES.DEMO,payload: action.payload});
};
export default function* saga() {/* // 创建监听器,当监听到派发后,才会继续向下执行// 特征:只能监听一次// action:可以获取派发时传递的actionlet action = yield take("DEMO-SAGA");yield working(action); */// 可基于循环,创建无限监听机制while (true) {let action = yield take("DEMO-SAGA");yield working(action);}
};

saga.js -> 其它监听器辅助函数的运用

const working = function* working(action) {console.log('AAA');// 设置延迟函数:等待2000ms后,才会继续向下执行!!yield delay(2000);yield put({type: TYPES.DEMO,payload: action.payload});
};
export default function* saga() {/* // 派发后,立即通知异步的working执行;// 但是在working没有处理完毕之前,所有其他的派发任务都不在处理!!while (true) {let action = yield take("DEMO-SAGA");yield working(action);} *//* // 每一次派发任务都会被执行yield takeEvery("DEMO-SAGA", working); *//* // 每一次派发任务都会被执行,但是会把之前没有处理完毕的干掉yield takeLatest("DEMO-SAGA", working); *//* // 每一次派发的任务会做节流处理;在频繁触发的操作中,1000ms内,只会处理一次派发任务yield throttle(1000, "DEMO-SAGA", working); *//* // 每一次派发的任务会做防抖处理;在频繁触发的操作中,只识别最后一次派发任务进行处理yield debounce(1000, "DEMO-SAGA", working); */
};

saga.js -> yield call/select…

import * as TYPES from './action-types';
import http from '../api/http';const working = function* working() {// 获取目前的公共状态信息let { num } = yield select(state => state.demo);// 从服务器获取数据// let result = yield apply(null, http.get, ['/api/news/latest']);let result = yield call(http.get, '/api/news/latest');console.log(result); //从服务器获取的数据yield put({type: TYPES.DEMO});
};
export default function* saga() {yield takeLatest("DEMO-SAGA", working);
};

saga.js -> yield fork

const query1 = function* query1() {console.log(1);yield delay(2000);
};
const query2 = function* query2() {console.log(2);yield delay(2000);
};
const working = function* working() {/* // 串行yield call(query1);yield call(query2); *//* // 并行:无阻塞调用yield fork(query1);yield fork(query2); */console.log(3);
};
export default function* saga() {yield takeLatest("DEMO-SAGA", working);
};

3. 基于redux-saga重写Vote案例

组件

import { useSelector, useDispatch } from 'react-redux';
import * as TYPES from '../store/action-types';
...
const Vote = function Vote() {const { supNum, oppNum } = useSelector(state => state.vote),dispatch = useDispatch();return <VoteBox>...<div className="footer"><Button type="primary"onClick={() => {dispatch({type: TYPES.VOTE_SUP});}}>支持</Button><Button type="primary"onClick={() => {dispatch({type: "VOTE-SUP-SAGA"});}}>异步支持</Button><Button type="primary" dangeronClick={() => {dispatch({type: TYPES.VOTE_OPP});}}>反对</Button><Button type="primary" dangeronClick={() => {dispatch({type: "VOTE-OPP-SAGA"});}}>反对异步</Button></div></VoteBox>;
};
export default Vote;

saga.js

import { takeLatest, put, delay } from 'redux-saga/effects';
import * as TYPES from './action-types';const voteSupWorking = function* voteSupWorking() {yield delay(2000);yield put({type: TYPES.VOTE_SUP});
};const voteOppWorking = function* voteOppWorking() {yield delay(2000);yield put({type: TYPES.VOTE_OPP});
};export default function* saga() {yield takeLatest("VOTE-SUP-SAGA", voteSupWorking);yield takeLatest("VOTE-OPP-SAGA", voteOppWorking);
};

redux-saga 常用API总结

1. 在组件中基于dispatch派发的时候,派发的action对象中的type属性「派发的行为标识」,它的命名上需要注意一个细节!!因为:每一次派发,一定会把reducer执行一遍,再去saga中间中,判断此任务是否被监听...如果打算进行“同步派发”:则我们派发的行为标识需要和reducer中做判断的行为标识保持一致!!并且在saga中,不要再对这个标识进行监听了!!这样的标识,我们可以在 store/action-types 中进行统一管理!!如果打算进行“异步派发”:我们派发的标识,“一定不能”和reducer中做判断的标识一样!!需要saga中对这个标识进行监听!监听到派发后,进行异步的操作处理!!我们可以在正常标识的后面加“@SAGA@”「规范:我自己定义的」当异步操作结束,我们基于 yield put 进行派发的时候,设置的派发标识,要和reducer中做判断的标识一样!!2. yield take(异步标识):创建监听器,监听派发指定标识的异步任务+ 单纯这样处理,只会被监听一次,我们特殊处理一下while (true) {let action = yield take(异步标识);yield workingCount(action);}3. yield takeEvery(异步标识,要执行的方法)+ 等价于上述基于while(true)的操作!!+ 本身就可以实现一直监听的操作!!被监到后,把传递进来的函数执行!!yield takeEvery(异步标识, workingCount);yield takeLatest(异步标识,working)+ 和takeEvery一样,每一次异步派发都会被监测到,都会把working执行+ 只不过,在执行working之前,会把正在运行的操作都结束掉,只保留当前最新的「也就是最后一次」+ 对异步派发任务的防抖处理「结束边界」yield throttle(ms, 异步标识, working);+ 对异步派发进行节流处理:组件中频繁进行派发操作,我们控制一定的触发频率「依然会触发多次,只不过做了降频」+ 它不是对执行的方法做节流,而是对异步任务的监测做节流:第一次异步任务被监测到派发后,下一次监测到,需要过“ms”这么长时间!!yield debounce(ms, 异步标识, working);+ 和takeLatest一样,也是做防抖处理「只识别一次」+ 但是原理和takeLatest是不一样的,和throttle类似:它是对异步任务的监测做防抖处理,在指定的“ms”时间内,我们触发多次,任务也只能被监测到一次「监测最后一次」,把working执行一次!!4. working工作区中使用的EffectsAPIyield delay(ms) 设置延迟操作「和我们之前自己写的delay延迟函数类型」,只有延迟时间到达后,其下面的代码才会继续执行!!yield put(action) 派发任务到reducer,等价于dispatchlet { ... } = yield select(mapState)+ 基于mapState函数,返回需要使用的公共状态+ yield处理后的结果,就是返回的公共状态,我们可以解构赋值let { num } = yield select(state => state.demo);let result = yield call(方法, 实参1, 实参2, ...)+ 基于call方法,可以把指定的函数执行,把实参一项项的传递给方法+ 真实项目中,我们一般基于call方法,实现从服务器获取数据+ result就是异步调取接口成功,从服务器获取的信息+ ...let result = yield apply(this, 方法, [实参1, 实参2, ...]);yield fork(方法, 实参1, 实参2, ...)+ 以 非阻塞调用 的形式执行方法

 

模拟接口

import {take, takeEvery, takeLatest, throttle, debounce,call, apply, fork, delay, put, select, all
} from 'redux-saga/effects';
import * as TYPES from './action-types';/* 模拟了两个接口 */
const api = {queryData(id, name) {return new Promise(resolve => {setTimeout(() => {let result = {code: 0,data: [10, 20, 30, 40]};resolve(result);}, 2000);});},queryBanner() {return new Promise(resolve => {setTimeout(() => {let result = {code: 0,data: '轮播图数据'};resolve(result);}, 1000);});}
};/* 创建执行函数,在任务被监听后,去做异步操作「Generator函数」 */
const workingCount = function* workingCount(action) {/* // let { num } = yield select(state => state.demo);yield delay(2000);// let { code, data } = yield call(api.queryData, 108, '珠峰');// let { code, data } = yield apply(null, api.queryData, [108, '珠峰']);yield put({type: TYPES.DEMO_COUNT,payload: action.payload}); *//* // 基于yield call处理,实现的是标准的串行效果:上一个请求成功,才会发送下一个请求let { data } = yield call(api.queryData, 100, '珠峰培训');console.log('第一个请求成功:', data);let { data: data2 } = yield call(api.queryBanner);console.log('第二个请求成功:', data2); *//* // 如果想实现并行效果,则基于yield all处理:等待所有请求都成功,再向下继续执行let { home, banner } = yield all({home: call(api.queryData, 100, '珠峰培训'),banner: call(api.queryBanner)});console.log(home, banner); //分别获取了两个请求成功的结果 */
};/* 创建监听器,监听派发的任务「Generator函数」 */
const saga = function* saga() {yield takeLatest(`${TYPES.DEMO_COUNT}@SAGA@`, workingCount);
};
export default saga;

 saga

import {take, takeLatest, throttle, debounce,call, apply, fork, delay, put, select, all, cancel
} from 'redux-saga/effects';
import * as TYPES from './action-types';/* 工作区域 */
const workingCount = function* workingCount(action) {yield delay(2000);yield put({type: TYPES.DEMO_COUNT,payload: action.payload});
};
const workingSupport = function* workingSupport() {yield delay(1000);yield put({type: TYPES.VOTE_SUP});
};
const workingOppose = function* workingOppose() {yield delay(1000);yield put({type: TYPES.VOTE_OPP});
};/* 创建监听器,监听派发的异步任务 */
const saga = function* saga() {/* while (true) {let action = yield take(`${TYPES.DEMO_COUNT}@SAGA@`);yield fork(workingCount, action);yield fork(workingSupport, action);yield fork(workingOppose, action);} */yield takeLatest(`${TYPES.DEMO_COUNT}@SAGA@`, workingCount);yield takeLatest(`${TYPES.VOTE_SUP}@SAGA@`, workingSupport);yield takeLatest(`${TYPES.VOTE_OPP}@SAGA@`, workingOppose);
};
export default saga;

http://www.khdw.cn/news/17333.html

相关文章:

  • 通化网站建设公司牛排seo系统
  • wordpress dux1.2seo自学教程推荐
  • 推广计划方案模板优化什么意思
  • 海南行指三亚网站开发seo站外推广
  • 深圳外贸网站建设值得收藏的五个搜索引擎
  • 做商城网站费用百度站长平台快速收录
  • 政府未来网站建设和发展规划十大电商代运营公司
  • 网页游戏排行榜2012长春seo网站排名
  • 建设工程的招标网站有哪些百度云资源链接分享群组
  • 北京专业企业营销网站建设目录搜索引擎有哪些
  • 建设单位物业服务企业武汉seo优化公司
  • 网站可以做多少事情徐州seo招聘
  • 网站在线制作平台国内最新新闻事件
  • 什么网站收录排名最高搜索词分析工具
  • 做网站教程第一课百度下载2022新版安装
  • 通过高新区网站建设百度seo优化推广公司
  • 太原做网站的公司电商培训课程
  • 企业宣传网站源码制作网站模板
  • 网站建设协议书模板 完整版创建一个网站
  • 网站设计优秀作品郑州seo
  • 外贸网站响应式快速网站轻松排名
  • 2018网站外链怎么做百度竞价关键词价格查询
  • php按步骤做网站网站建设与营销经验
  • 有哪些网站做电子元器件比较好株洲企业seo优化
  • 政府查询网站建设方案网搜网
  • 解答网站内容优化策略广州seo站内优化
  • wordpress 编辑器 视频教程长沙靠谱seo优化费用
  • 有关网站开发的论文seo推广培训课程
  • 网站产品标签文章标签怎么做的qq推广链接生成
  • 如何建立网站卖东西可以发布推广引流的悬赏平台