redux-saga

这篇具有很好参考价值的文章主要介绍了redux-saga。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、迭代器和生成器

1、迭代器iterator
1.1、为什么需要迭代器
1.2、什么是迭代

迭代器从一个数据集合中按照一定的顺序,不断的取出数据的过程

Iterator的作用

  • 为各种数据结构,提供一个统一的接口

  • 使得数据结构的成员能够按某种次序排列

  • 迭代强调是依次取出,不能确定取出的有多少,也不能保证把数据全部取完

迭代和遍历的区别

  • 迭代强调的依次取出,不能确定可以取出的值有多少,也不能保证去吧数据全部取完

  • 遍历必须保证数据的长度,循环不断的全部取出,针对于数据量过大的情况下使用遍历需要时间过长

2.2、基本语法

迭代器是一个特殊的对象,每一个迭代器对象身上都有一个 next() 方法;调用 next() 会返回一个对象,该对象中包含 value 属性和 done 属性

我们用 ES5 的代码来模拟创建一个迭代器:

const colors = ['red', 'yellow', 'green', 'blue'];
​
function createIterator(items) {
    let i = 0;
    // 返回一个迭代器对象
    return {
        next: function () {
            if (i < items.length) {
                return { value: items[i++], done: false }
            }
            return { value: undefined, done: true }
        }
    }
}
​
const iterator = createIterator(colors);
let result = iterator.next();  // { value, done }
// 只要 done 属性的值为 false,就表示循环还未结束
while (!result.done) {
    console.log(result.value);
    result = iterator.next();
}

分析Iterator的遍历过程:

  • 创建一个对象,指向当前数据结构的起始位置

  • 随后通过 next 方法进行向下迭代指向下一个位置, next 方法会返回当前位置的对象, 对象包含了 value 和 done 两个属性, value 是当前属性的值, done 用于判断是否遍历结束

  • 当done为true时,迭代结束

2.3、在类中添加迭代器

在es6中,如果对象具有知名符号的属性 Symbol.iterator,则表示对象可以迭代

ES6 的有些数据结构原生具备 Iterator 接口(比如数组),即不用任何处理,就可以被for…of循环遍历:

let items=['red','yellow','blue','green']
const iterator=items[Symbol.iterator]()
const it1=iterator.next()   
console.log(it1);  //{ value: 'red', done: false }
const it2=iterator.next()
console.log(it2);  //{ value: 'yellow', done: false }
const it3=iterator.next()
console.log(it3);  //{ value: 'blue', done: false }
const it4=iterator.next()
console.log(it4);  //{ value: 'green', done: false }
const it5=iterator.next()
console.log(it5);  //{ value: undefined, done: true }

自定义可迭代对象:

  let person={
         name:'Giles',
         age:23,
         [Symbol.iterator]:function(){
            let keys=Object.keys(this).filter(item=>item!='values')
            //定义index为下标
            let index=0
            return{
                next:()=>{
                   //获取对象的属性名
                   let proName=keys[index]
                   let proval=this[proName]
                   let result={
                      value:{proName,proval},
                      done:true
                   }
                   index++
                   return result
                }
            }
         }
       }
​
       for(let item of person){
         console.log(item);
       }
2.4、调用迭代器的场景

迭代器的使用场景还是蛮多的,解构赋值、扩展运算符、Generator函数、yield*, 下方会简单的列举出来

(1)、 对数组或者集合的解构赋值

let myset=new Set()
myset.add('Giles')
myset.add('Monica')
myset.add('Lucy')
myset.add('Lily')
myset.add('Jerry')
const [first,second,...others]=myset;
console.log(first,second,others);

(2)、扩展运算符

let ary="HelloGiles"
console.log([...ary]);

(3)、 在Generator函数的 yield * 中使用

稍后会详细的介绍 Generator 函数

2、生成器 generator

generator 是 ES6 中新增的一个异步解决方案。

生成器 generator 是一个函数,该函数的返回值是一个迭代器对象。

2.1、创建生成器函数

创建生成器函数的基础语法如下:

function* 函数名() {
​
}

在创建生成器函数时,需要在 function 关键字和函数名之间,添加一个 * 星号。

2.2、调用生成器函数

要调用生成器函数,和普通函数一样,还是要先通过 函数名() 的形式来实现。但是,当我们调用完后会发现,函数内的代码并没有执行。

因为通过 函数名() 的形式调用生成器函数,会得到一个迭代器对象,如果需要执行生成器函数内部的代码,需要调用迭代器的 next() 方法。

生成器函数的调用基础语法如下:

const iterator = 函数名();
iterator.next();
2.3、yield 关键字

在生成器函数中,可以使用 yield 关键字。

yield 关键字可以用来阻塞生成器函数中代码的执行,也就是说,当生成器函数中的代码执行到 yield 时,会暂停执行。

例如:

function* myGenerator() {
    console.log('1、hello');
    console.log('2、hello');
    yield;
    console.log('3、hello');
}
const iterator = myGenerator();
iterator.next();

如果希望生成器函数中代码继续往后执行,需要再次调用 next()

function* myGenerator() {
    console.log('1、hello');
    console.log('2、hello');
    yield;
    console.log('3、hello');
}
const iterator = myGenerator();
iterator.next();  // { value: undefiend, done: false }
iterator.next();  // { value: undefiend, done: true }

每一次调用 next() 方法,该方法都会返回一个对象,包含 valuedone 属性,done 属性可以用来表示当前函数是否执行完成,如果 done: true,则表示函数内的代码已经执行完毕。

1)yield 搭配表达式

yield 关键字的后面,还可以跟一个表达式。基础语法如下:

function* 函数名() {
    // 函数体内容
    yield 表达式;
}

yield 关键字后面的值,会作为 next() 返回对象的 value 属性值。

例如:

function* myGenerator() {
    yield 'hello';
}
const iterator = myGenerator();
iterator.next();  // { value: 'hello', done: false }

也就是说,我们可以通过 yield 表达式,将生成器函数内部的数据传递到函数外部。

2)yield 的返回值

当我们调用 next() 方法时,可以通过 next() 方法往生成器函数中传递数据,最终,这个数据会作为上一次 yield 的返回值接收。

案例代码:

function* myGenerator() {
    console.log(1);
    const num = yield;
    console.log(num);  // 2
} 
const iterator = myGenerator();
iterator.next();   // 1
iterator.next(2);
2.4 使用Generator函数进行异步编程
function getPromise(params,timeout){
    return new Promise((resolve,reject)=>{
        setTimeout(() => {
            resolve(`response:${params}`)
        }, timeout);
    })
}

function * gen(){
    try {
        yield getPromise('success1',2000)
        yield getPromise('success2',1000)
        yield getPromise('success3',3000)
        yield getPromise('success4',4000)
        yield getPromise('success1',2000)
    } catch (error) {
        console.log(error);
    }
}

for(let result of gen()){
    console.log(result);
    result.then(value=>{
        console.log(`执行的结果是:${value}`);
    })
}

二、Redux-saga

1.Redux-saga概述

redux-saga是一个用于管理应用程序Side Effect副作用(例如:异步获取数据,访问浏览器缓存等)的library,它的目的是让副作用管理更加的简单,执行更加高效。

redux-saga就是redux的一个中间件,可以通过正常的redux action从主应用程序启动,暂停和取消,它可以访问完整的redux saga,也能够dispatch redux action

redux-saga使用了ES6的Generator功能,让异步流程更加易于读取,写入和测试,通过这种方式,让异步看起来更加像标准同步的js代码。

Redux官方网址:Redux-Saga - An intuitive Redux side effect manager. | Redux-Saga

2、redux-saga的安装
yarn add redux-saga
3、redux-saga的原理图

redux-saga,javascript,前端,开发语言

3、redux-saga获取购物车信息

1)在src/components/ShopCartList.jsx中编写如下代码

import React,{useEffect} from 'react'
import {useDispatch} from 'react-redux'

export default function ShopCartList() {
  const dispatch=useDispatch()
  useEffect(()=>{
    dispatch({type:'getShopCartListAsync'})
  },[])
  return (
    <div>
        <h2>购物车列表</h2>
    </div>
  )
}

如上代码,主要是在页面加载完毕后,向saga文件dispatch一个请求

  1. 在redux/saga.js文件中,编写如下方法,主要完成监听组件发送过来的通知

import {takeEvery} from 'redux-saga/effects'
function * getShopCartList(){
    console.log('--------准备向网络购物车信息-----------');
}

function * index(){
    yield takeEvery('getShopCartListAsync',getShopCartList)
}

export default index
  1. 在src/redux/store.js中,编写如下

import {legacy_createStore as createStore,applyMiddleware} from 'redux'
import shopCartListReducer from './reducer/shopCartListReducer'
import createSagaMiddleware from 'redux-saga'
import saga from '../redux/saga'
const sagaMiddleware=createSagaMiddleware()
const store=createStore(shopCartListReducer,applyMiddleware(sagaMiddleware))
sagaMiddleware.run(saga)
export default store

4)在index.js文件上使用<Provider>将跟组件进行包裹

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {Provider} from 'react-redux'
import store from './redux/store'
const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
    <Provider store={store}>
         <App />
    </Provider>
);  

5)在redux/saga.js文件中,完成异步网络请求,并将结果通过reducer保存到仓库中

function * getShopCartList(){
    const result=yield call(api.shopcart.getshopcartListApi)
    console.log(result.data.data);
    yield put(shopcartListAction(result.data.data))
}

6)在src/components/ShopCartList.jsx组件中通过useSelector钩子函数来接收仓库中的数据

const list=useSelector((state)=>{
    return state.shopcartList
})

7)然后在购物车组件中将列表数据渲染出来

import React,{useEffect,useMemo} from 'react'
import {useDispatch,useSelector} from 'react-redux'

export default function ShopCartList() {
  const dispatch=useDispatch()
  useEffect(()=>{
    dispatch({type:'getShopCartListAsync'})
  },[])
  //从仓库中获取购物车列表数据
  const list=useSelector((state)=>{
    return state.shopcartList
  })
  //完成计算商品总价
  const total=useMemo(()=>{
    return list.filter(item=>item.checked).reduce((pre,cur)=>pre+cur.price*cur.num,0)
  },[list])
  return (
    <div>
        <h2>购物车列表</h2>
        <table>
           <thead>
                <tr>
                    <td>序号</td>
                    <td>名称</td>
                    <td>单价</td>
                    <td>数量</td>
                    <td>小计</td>
                    <td>更新时间</td>
                </tr>
           </thead>
           <tbody>
              {
                list.map((item,index)=><tr key={item._id}>
                    <td>
                        <input type="checkbox" checked={item.checked}/>
                    </td>
                    <td>
                        {item.name}
                    </td>
                    <td>
                        {item.price}
                    </td>
                    <td>
                        <button>-</button>
                        {item.num}
                        <button>+</button>
                    </td>
                    <td>
                        {item.price*item.num}
                    </td>
                    <td>
                        {item.updateDate}
                    </td>
                </tr>)
              }
              <tr>
                <td colSpan={5}>
                    总价:{total}
                </td>
              </tr>
           </tbody>
        </table>
    </div>
  )
}
4、redux-saga更新购物车商品数量

1)在ShopCart.jsx组件中绑定事件

<button onClick={()=>{changeNum(item._id,-1)}}>-</button>
{item.num}
<button onClick={()=>{changeNum(item._id,1)}}>+</button>
const changeNum=(_id,n)=>{
    dispatch({type:'changeNumAsync',_id,n})
}
  1. 在saga.js文件中添加监听方法

function * index(){
    yield takeEvery('changeNumAsync',changeNum)
}
  1. 在saga.js文件中编写changNum生成器方法,用来实现异步请求

function * changeNum({_id,n}){
    const result=yield call(api.shopcart.changeNumApi,{_id,n})
    if(result.data.code){
        yield put({type:'getShopCartListAsync'})
    }
}
5、redux-saga实现勾选商品信息

1)在ShopCart.jsx组件中绑定事件

<input type="checkbox" checked={item.checked} onChange={()=>{checkedItem(item._id)}}/>
const checkedItem=(_id)=>{
    dispatch({type:'checkedItemAsync',_id})
}

2)在saga.js文件中添加监听方法

function * index(){
    yield takeEvery('checkedItemAsync',checkedItem)
}

3)在saga.js文件中编写checkedItem生成器方法,用来实现异步请求文章来源地址https://www.toymoban.com/news/detail-680684.html

function * checkedItem({_id}){
    const result=yield call(api.shopcart.checkProductApi,_id)
    if(result.data.code){
        yield put({type:'getShopCartListAsync'})
    }
}

到了这里,关于redux-saga的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 30个前端开发中常用的JavaScript函数

    🧑‍💻作者名称:DaenCode 🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。 😎人生感悟:尝尽人生百味,方知世间冷暖。 在前端开发中通常会用到校验函数,检验是否为空、手机号格式、身份证格式等等。现按照用途分类整理出了30个常用的方法,在V

    2024年02月14日
    浏览(46)
  • 2023年web前端开发之JavaScript进阶(一)

    接上篇博客进行学习,通俗易懂,详细 博客地址: 2023年web前端开发之JavaScript基础(五)基础完结_努力的小周同学的博客-CSDN博客 学习 作用域 、变量提升、 闭包 等语言特征,加深对 JavaScript 的理解,掌握变量赋值、函数声明的简洁语法, 降低代码的冗余度 。 理解作用域对程序

    2024年02月03日
    浏览(57)
  • [前端开发] 常见的 HTML CSS JavaScript 事件

    代码示例指路 常见的 HTML、CSS、JavaScript 事件代码示例 在 Web 开发中,事件是用户与网页交互的重要方式之一。通过事件,用户可以与页面元素进行交互,触发相应的功能或效果。本文将介绍常见的 HTML、CSS、JavaScript 事件,以及事件对象和事件代理的概念。 鼠标事件 鼠标事

    2024年02月19日
    浏览(56)
  • 【前端】React快速入门+Redux状态管理

    本文旨在记录react的基础内容,帮助有需要的同学快速上手,需要进一步了解描述更加稳妥和全面的信息,请查阅官方文档 官方文档点击这里进行跳转 react框架 vue,react,angular这几种主流前端框架使用频率较高…本质还是js库。 React.js是一个用于构建用户界面的JavaScript库。它由

    2024年02月12日
    浏览(50)
  • 建站系列(五)--- 前端开发语言之HTML、CSS、JavaScript

    建站系列(一)— 网站基本常识 建站系列(二)— 域名、IP地址、URL、端口详解 建站系列(三)— 网络协议 建站系列(四)— Web服务器之Apache、Nginx 建站系列(五)— 前端开发语言之HTML、CSS、JavaScript 建站系列(六)— 后端开发语言 建站系列(七)— 常用前后端框架

    2024年02月09日
    浏览(56)
  • 从javascript到vue再到react:前端开发框架的演变

    目录 JavaScript: 动态语言的基础 JavaScript:Web开发的起点 Vue.js: 渐进式框架的兴起 Vue.js:简洁、高效的前端框架 React.js: 声明式UI的革新 React.js:强大、灵活的前端框架 演变之路与未来展望 演变过程 当提到前端开发中的框架时,JavaScript、Vue.js和React.js是三个最常见的名词。它

    2024年02月07日
    浏览(53)
  • 【前端知识】React 基础巩固(三十一)——Redux的简介

    概念 纯函数(确定的输入一定产生确定的输出,函数在执行过程中不产生副作用): 在程序设计中,若一个函数符合以下条件,那么这个函数就被称为纯函数 此函数在相同的输入值时,需产生相同的输出 函数的输出和输入值以外的其他隐藏信息或状态无关,也和由I/O设备产

    2024年02月16日
    浏览(53)
  • 《JavaScript前端开发案例教程》课后习题及答案(黑马程序员编著)

    一、填空题 1.window.document.body可以简写为______。 2.console.log(alert(‘Hello’))在控制台的输出结果是______。 3.编辑器中“以UTF-8无BOM格式编码”中的BOM指的是______。 4.alert(‘测试’.length)的输出结果是______。 二、判断题 1.JavaScript是Java语言的脚本形式。( ) 2.JavaScript中的方法名不

    2024年02月09日
    浏览(56)
  • 【前端知识】React 基础巩固(三十三)——Redux的使用详解

    针对 React 基础巩固(三十二) 中的案例,我们希望抽取页面中共有的代码(例如下方的代码),使用高阶组件统一拦截。 为了让react和redux产生联系,安装一款工具 react-redux 使用 react-redux ,在index.js中统一注入store 新建about.js页面,通过 react-redux 引入store 在App.jsx中引入新的

    2024年02月15日
    浏览(52)
  • [HTML]Web前端开发技术26(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页

    希望你开心,希望你健康,希望你幸福,希望你点赞! 最后的最后,关注喵,关注喵,关注喵,佬佬会看到更多有趣的博客哦!!! 喵喵喵,你对我真的很重要! 目录 前言 数据类型 数据类型-字符型 数据类型-数值型 数据类型-布尔型 数据类型-其它类型 变量 转义字符 运算

    2024年02月20日
    浏览(70)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包