前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >『Dva』异步处理

『Dva』异步处理

原创
作者头像
程序员 NEO
修改2024-12-01 07:54:14
修改2024-12-01 07:54:14
11500
代码可运行
举报
运行总次数:0
代码可运行

推荐文章

简介

链接

从零玩转系列之腾讯云微信扫码授权系统

这篇文章是技术实战类型的,作者通过详细的步骤和代码示例,展示了如何从零开始搭建一个微信扫码授权系统。文章内容涵盖了技术选型、业务流程解析、后端实现、接口调用等多个方面,对于想要了解或实现类似功能的开发人员来说,是一篇非常有价值的参考文章。

一、前言

🐤本篇文章是『从零玩转 TypeScript + React 项目实战』系列文章的第 5 篇,主要介绍『Dva』异步处理

经过上一篇『Dva』管理数据,文章的介绍,了解了如果通过 Dva 来管理我们的数据,了解了一下 Dva 当中的 Model,了解了下如何使用 Model 来保存我们的数据,了解了下如何使用 Model 来保存 Reducer。

那么了解完了这些内容之后呢,本篇文章再来看一下 Model 当中的 Effect。

二、Effect

2.1 什么是 Effect

Effect 的意思就是副作用,这个副作用用什么作用呢?它是专门用来处理异步数据的,怎么处理的呢?其实也非常的简单,这个时候先来看看 DvaJS 的官方文档中的介绍。

DvaJS 文档地址:https://dvajs.xiniushu.com/guide/

然后找到头部右侧的 API 查看一下:

进入到 API 文档页面之后我们找到 Model,找到 Model 之后它就会展示告诉我们如何来编写 Model:

2.2 如何使用 Effect

编写 Model 是不是可以指定命名空间,是不是可以指定我们要保存的数据(state),是不是可以指定 reducers,除了可以指定 reducers 外,是不是还可以指定 effects,如下图:

所以说,接下来我该怎么做呢,我先回到我自己的代码当中,找到我编写的 homeModel,在我 homeModel 里面呢,再来给它新增一个 effects,如下图:

新增了 effects 之后,就可以在这里面做一些异步操作了,异步操作怎么做的呢?这个时候回到官方文档进行查看,发现它定义了一个生成器函数,这个生成器函数我们在哪见过,是不是在我之前使用 saga 的时候见过,对吧,所以说这里面是专门用来放什么的呢,这里面就是专门用来放 saga 当中处理异步数据的代码,所以说接下来该怎么做呢,我可以找到我过去讲解 saga 的时候的代码。

过去我在讲解 saga 的时候我是不是定义了一个 myHandler 这么一个生成器函数,专门用它来处理异步数据,是不是只要它被执行了,就会发送网络请求去请求数据,把数据保存到 data 中,保存之后再通过 put,来派发一个任务,然后再把获取到的数据保存到 state 中,这样就可以了:

所以说可以怎么做呢?我可以直接将之前的代码拿过来,再拿过来之前呢,数据是不是将来要保存到某一个地方,先找到 homeModel 中的 state,新增一个 info 属性取值是一个对象,将来呢把数据保存到 info 里面,保存到 info 里面怎么保存是不是通过 reducers 来处理,在 reducers 中新增一个 changeInfo 类型的 action,接收两个参数分别是 state,action,changeInfo action 大致结构如下:

代码语言:javascript
代码运行次数:0
复制
changeInfo: (state, action) => {
    return {}
}

好,定义好了,由于 state,中有多个数据,为了避免数据丢失。我应该先把以前的所有数据都全部重新拷贝一次,然后再用新的数据来覆盖掉同名的数据,现在的数据是不是在 action 当中:

代码语言:javascript
代码运行次数:0
复制
changeInfo: (state, action) => {
    return {
        ...state,
        info: action.info
    }
}

经过如上所实现的 changeInfo 方法,我现在就已经可以保存数据了,接下来我再将之前在 saga 中获取异步数据的代码拷贝到我现在演示的 demo 项目中使用了:

代码语言:javascript
代码运行次数:0
复制
* asyncUserInfo(state, {put}) {
    // 获取网络数据
    const data = yield fetch('http://localhost:4000/api/data')
        .then((response) => {
            return response.json();
        })
        .catch((error) => {
            console.log(error);
        });
    yield put({type: 'changeInfo', info: data.data});
},

异步处理方法名称叫做 asyncUserInfo,这个代码的含义呢代表什么呢?将来只要我派发了一个 type 名称叫做 asyncUserInfo 的这么一个 action,就会执行 asyncUserInfo 中的内容,执行 asyncUserInfo 的时候会将过去的数据(也就是 state)给你,还会给你一个对象,这个对象当中就保存了 saga 当中内置的一些方法,比如说保存了 put,保存了 call,这类似的东西。

这些东西过去我们都是需要自己手动从 saga 中的 effects 当中,手动去导入:

现在呢,现在就不用了当执行 asyncUserInfo 的时候它会直接把 effects 这个对象传递给你,所以说这里可以直接解构出来所需要的方法使用即可。所以如上呢我就解构出来了 put 供我使用,然后通过:

代码语言:javascript
代码运行次数:0
复制
yield fetch('http://localhost:4000/api/data')
.then((response) => {
    return response.json();
})
.catch((error) => {
    console.log(error);
});

先获取数据,保存到一个 data 变量中,然后再通过 put 派发一个任务,将获取到的数据存起来,我这里派发了一个 changeInfo 任务将本次获取到的数据传递了过去。

这里有个注意点本人要说明一下,http://localhost:4000/api/data 这个请求地址说我本人,用 express 框架搭建起来的服务,供我自己测试使用,其实网上有那种开发式的测试接口,我说没去找,对于懒得搭建的人来说可以去试试,但是呢这个源码我已经上传到我自己的 Git 仓库了。

地址:https://github.com/BNTang/dva-demo-service

clone 下来之后 npm install 然后运行起来即可。好这个问题我说完了。

继续回到 asyncUserInfo 中的派发任务代码处继续讲,这里我派发完任务之后,系统就会找到 changeInfo 这个哥们去执行它,changeInfo 所对应的 type 为 changeInfo,然后 info 中就是存储的一些数据:

到此,已经编写完成了,已经没问题了,没问题之后呢,接下来就到了要使用一下测试一下看看效果的时候了,运行之前,先看看整体流程。

三、流程梳理

我先贴一张 dva 的图,让大家先回忆一下:

过去我说过,只要通过 dispatch 派发一个 action dva 会把 action 传递给 Reducer 和 Effect,运行过程如下图:

怎么传的呢?首先找到 reducers,看看 reducers 中有没有一个叫做 asyncUserInfo,很显然我们的 reducers 中是没有的,没有的话,它就会去看 effects 看 effects 里面有没有 asyncUserInfo,我代码中是不是编写了,也就是有,有!怎么办,那就执行,执行 asyncUserInfo:

asyncUserInfo 就会去获取网络数据,获取完网络数据之后又派发了一个 changeInfo:

将本次所获取到的数据带过去,这个时候,我们又派发了一个 action 它是不是首先会去找到 reducers,在 reducers 中找有没有 changeInfo,很显然是有,那么就执行,执行完之后就将数据存起来了。

四、测试

用一下试一下,该怎么做呢,很简单,首先找到,映射数据的代码区域位置,在映射一个 info,更改 mapStateToProps 这个 info 数据从命名空间为 home 的这个 Model 当中去映射:

代码语言:diff
复制
const mapStateToProps = (state) => {
    return {
        // 需要从传入的 state 的命名空间中拿到对应 Model 保存的数据
        count: state.home.count,
+       info: state.home.info
    }
};

映射完之后,就可以进入到使用阶段了,进入到 Home 组件中将数据展示一下,分别定义两个 p 标签,和一个按钮,这个按钮就是用来映射,当按钮点击之后所要执行的方法的。

由于 http://localhost:4000/api/data 接口返回的数据格式如下:

分别有 name、id、role,页面上就只能展示这三个字段的内容:

代码语言:diff
复制
function Home(props) {
    return (
        <div>
            <p>{props.count}</p>
            <button onClick={() => {
                props.increment()
            }}>+
            </button>
            <button onClick={() => {
                props.decrement()
            }}>-
            </button>
+           <hr/>
+           <div>dva异步处理</div>
+           <p>{props.info.name}</p>
+           <p>{props.info.role}</p>
+           <button onClick={() => {
+               props.getUserInfo()
+           }}>获取
+           </button>
        </div>
    )
}

由于按钮需要映射一个 getUserInfo 方法,这个 getUserInfo 方法还没有现在就去编写一下,来到映射方法的代码当中也就是 mapDispatchToProps 的内容。

在 mapDispatchToProps 中开发一个 getUserInfo,通过 getUserInfo 派发一个任务,往命名空间是 home 的这个 Model 当中派发一个 effects 当中的 asyncUserInfo 就可以了代码实现如下:

代码语言:diff
复制
const mapDispatchToProps = (dispatch) => {
    return {
        increment() {
            dispatch({type: 'home/add', count: 1});
        },
        decrement() {
            dispatch({type: 'home/sub', count: 1});
        },
+       getUserInfo() {
+           dispatch({type: 'home/asyncUserInfo'});
+       }
    }
};

好,代码编写到这就结束了,将 server 与 dva 项目都起起来看看实际跑起来的情况:

ok,非常的好,这个数据返回的与我服务端返回的是一模一样的,这样就没问题了,这样就可以获取到我们的异步数据了,所以说以后在企业开发当中,如果你是通过 dva 来管理数据,如果说你需要在 dva 里面进行异步操作,怎么办,同步的写到 reducers 中,异步写到 effects 中就可以了。

也就是说,你只需要把过去 saga 当中处理异步数据的生成器函数放到 dva 当中的 effects 当中这样就可以了。

五、总结

通过本文的学习,您可以掌握以下知识点:

  • 1.Dva 中的 Effect 的定义与作用:了解 Effect 是专门用于处理异步操作的,可以利用生成器函数对数据进行异步获取、处理并派发新的 action。
  • 2.如何在 Model 中编写 Effect:掌握如何在 Model 中定义 effects 并利用 put 方法派发 action 更新 state。
  • 3.Dva 中异步操作的流程:从 dispatch 一个 action 到 effects 中的异步操作执行,再到 reducers 中对 state 的最终更新。
  • 4.如何映射数据和方法到组件:熟悉 mapStateToPropsmapDispatchToProps 的用法,能将 state 和 action 映射到组件的 props 中。
  • 5.Dva 的实际操作示例:通过实例代码,深入理解如何在实际项目中编写并调试异步操作。

🐤如果您觉得本文对您有所帮助,欢迎点赞、收藏或分享,您的支持是我创作的最大动力!

这篇文章的内容就介绍到这里,期待我们下次的相遇。感谢您花时间阅读,如果有任何问题或想法,欢迎在评论区留言。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、Effect
    • 2.1 什么是 Effect
    • 2.2 如何使用 Effect
  • 三、流程梳理
  • 四、测试
  • 五、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档