Action 类似于 mutation,不同在于:

1.Action 提交的是 mutation,而不是直接变更状态。

2.Action 可以包含任意异步操作。

官方给的定义我没什么意见,事实上我通过mutation异步操作,好像跟用action管理也没什么区别。关于为什么要用Action管理异步操作,我会通过一个简单的例子和一个复杂的例子来进行说明,事实上,如果初学者没有考虑到实际场景的复杂情况,会觉得Action根本没有一点软用,这个时候就要把问题想得复杂一些了,然后才能看到Action的作用。

先来看一个简单的例子,也是我对如果不用Action进行异步操作的一些初步探索。

第一步:我非常作死的重写了mutation状态管理器中对状态操作的一些写法,我使用了异步操作代替了之前的操作。

// mutation.js
const increment = (state) => {
setTimeout(() => {
state.count++
}, )
}
const decrement = (state) => {
setTimeout(() => {
state.count--
}, )
state.count--
}
export {increment, decrement}

第二步:试验一下能否成功

<template>
<div>
<button @click="decrement">-</button>
<span>{{count}}</span>
<button @click="increment">+</button>
</div>
</template>
<script>
import { mapState, mapMutations} from 'vuex'
export default {
computed: {
...mapState(['count'])
},
methods: {
...mapMutations(['increment', 'decrement']),
}
}
</script> <style> </style>

第三步:发现除了每次操作加减时候有一秒的延时,不管你怎么操作,结果都是正确的,是符合社会主义核心价值观的。

第四步:用Action处理异步操作(先得把之前作死改掉的mutation的代码改回来)

// 正常的mutation
const increment = (state) => {
state.count++
}
const decrement = (state) => {
state.count--
}
export {increment, decrement}
// action.js处理一些异步操作

// Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象
let incrementAsync = (content) => {
setTimeout(() => {
content.commit('increment')
}, )
}
let decrementAsync = (content) => {
setTimeout(() => {
content.commit('decrement')
}, )
}
export {incrementAsync, decrementAsync}
<template>
<div>
<button @click="decrementAsync">-</button>
<span>{{count}}</span>
<button @click="incrementAsync">+</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
computed: {
...mapState(['count'])
},
methods: {
...mapMutations(['increment', 'decrement']),
...mapActions(['incrementAsync', 'decrementAsync']) //这里用了辅助函数,不了解的可以看这个系列的第二篇文章
}
}
</script> <style> </style>

第五步:测试一下效果,你会感觉跟没有用action直接用mutation的结果一毛一样。再看一下官网说明。

所以,官网说的这句话有问题?
 确实有问题,因为在mutation中执行异步操作并不会报错,也能正确更改状态,所以并不是所谓的“必须同步执行”这么苛刻,只能说你最好不要这么做。(这里说一句题外话,我初学vuex的时候,大概去年,在mutaition中一旦有异步操作,控制台立马就会有警告,不知道是记错了还是现在删除了这个设定)

上面的例子可能太过简单,以至于Action看起来都发挥不了什么作用。

下面来看一个复杂的例子,这个例子有助于理解为什么要用Action管理异步操作
需求如下

state中存储了一个状态,我们还是复用刚才的count

现在有两个异步操作,他们都能改变count的值

第二个异步操作的条件依赖第一个异步操作的结果,比如第一个异步操作执行了count ++ ,count :0 = >1,第二个异步操作会先判断当前count的值,if(count === 1) { do something...} else { do something... }

当异步操作涉及互相依赖的情况的时候,我们肯定希望被依赖的操作执行完成之后,再执行依赖项,这样能保证程序执行得到正确的结果,但异步操作,如接口访问这种,往往是不能确定执行完成的时间的,

通常你在接口A中得到一个值,a

接口B需要使用这个值结合B接口返回的值进行一些判断操作,if(a&&b){ ... }

这个时候如果B接口执行完毕了,A接口的值还没过来的话,就可能得到错误的结果。 a => undefined

所以这里牵扯到了一个异步操作的顺序执行问题,既然是异步操作问题,基本都会用到ES6的promise函数去解决,有兴趣的可以用看一下我的文章——关于promise的一些使用和原理。

下面我们重写一下代码

// Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象
let incrementAsync = (content) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
content.commit('increment')
resolve()
}, )
})
}
let decrementAsync = (content) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
content.commit('decrement')
resolve()
}, )
})
}
export {incrementAsync, decrementAsync}
})
<template>
<div>
<button @click="dec">-</button>
<span>{{count}}</span>
<button @click="add">+</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
computed: {
...mapState(['count'])
},
methods: {
...mapMutations(['increment', 'decrement']),
...mapActions(['incrementAsync', 'decrementAsync']),
add () {
this.incrementAsync().then(() => {
this.increment()
})
},
dec () {
this.decrementAsync().then(() => {
// do something
})
}
}
}
</script> <style> </style>

关于Action,细枝末节的东西并不想多讲,比如action中的‘载荷’,mapAction辅助函数,promise()函数使用等等,都是之前讲过的,写这篇文章的目的还是想重申一下为什么要用Action管理异步操作,有些人可能觉得如果一种代码可以用另一种看起来可以实现的方式实现的话,就不用去管“规范”的问题了,反而觉得这看起来更像一个“黑客”的做法,从而刻意的追求程序的“自由性”。

我只能说,你可以这么做,但请你善待帮你维护代码的人,因为你的“自由开发”可能让别人完全搞不懂你在写什么,只想骂你是个傻X。

Vuex入门(5)—— 为什么要用Action管理异步操作的更多相关文章

  1. vuex入门教程和思考 [转] 里面有几个实例

    Vuex基础概念 vuex中涉及的概念主要有下面几点,下面做个简单的介绍和理解. Vuex 官方文档:https://vuex.vuejs.org/zh-cn/ 官网有介绍,也有个demo shopp ...

  2. vuex 入门

    vuex.js 状态(数据)管理 在vue中当我们管理数据的时候比较乱,我们要用到下面的这个库,vuex.js Vuex介绍 每一个Vuex应用的核心就是store(仓库),他是用来存储数据的 &qu ...

  3. Vuex入门实践(中)-多module中的state、mutations、actions和getters

    一.前言 上一篇文章<Vuex入门实践(上)>,我们一共实践了vuex的这些内容: 1.在state中定义共享属性,在组件中可使用[$store.state.属性名]访问共享属性 2.在m ...

  4. untiy3d action管理机制的编写

    使用unity3d对于一些可视化强迫者来说,是一个不错的选择,但unity3d没有cocos2d的action管理机制,比如cocos2dx的CCMoveTo,CCScale等action,所以笔者通 ...

  5. [转帖]从零开始入门 K8s:应用编排与管理:Job & DaemonSet

    从零开始入门 K8s:应用编排与管理:Job & DaemonSet https://www.infoq.cn/article/KceOuuS7somCYbfuykRG 陈显鹭 阅读数:193 ...

  6. Vuex 入门指南

    1.Vuex是什么? 我们还是像以往一样先看一看官方文档对此的解读(Vuex 是什么? · GitBook) Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的 ...

  7. Vuex 模块化实现待办事项的状态管理

    前言 在vue里,组件之间的作用域是独立的,父组件跟子组件之间的通讯可以通过prop属性来传参,但是在兄弟组件之间通讯就比较麻烦了.比如A组件要告诉一件事给B组件,那么A就要先告诉他们的爸组件,然后爸 ...

  8. vuex入门

    安装&使用 npm install vuex --save 1 通过Vue.use()来使用: import Vue from 'vue' import Vuex from 'vuex' Vu ...

  9. vuex入门教程和思考

    Vuex是什么 首先对于vuex是什么,我先引用下官方的解释. Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可 ...

随机推荐

  1. Atitit 热烈庆祝读经器项目圆满完成

    Atitit 热烈庆祝读经器项目圆满完成 1.1. 读经器项目简单介绍 1 1.2. 一万小时定律和十年一个专家定律 1 1.3. 获得加持前景 1 1.4. 核心源码 1 1.5. 项目git 2 ...

  2. 修改Egret引擎代码的方法

    某些情况下,我们需要修改Egret引擎的源码,我们可以在源码目录(一般如下:xxx\Egret\engine\x.x.x\src\egret)下直接修改ts代码. 在对应的项目下打开CMD命令行,输入 ...

  3. 【CFD之道】2017年原创文章汇总

    1 Fluent案例(21篇) [Fluent案例]01 空气流经障碍物 [Fluent案例]02:Tesla阀 [Fluent案例]03:RAE2822翼型外流场计算 [Fluent案例]04:多孔 ...

  4. 物联网系统与CoAP之Hello,World

    物联网系统与CoAP Hello,World 关于CoAP与物联网系统我们在上一篇中(ps:CoAP与物联网系统)中做一个简单的介绍,接着我们便開始试试CoAP协议的应用 CoAP应用 開始之前我们须 ...

  5. unity3d IL2CPP for android

    unity3d 使用IL2Cpp导出android工程报以下错误解决方法 重点是这块 “”System.Reflection.TargetInvocationException: ���õ�Ŀ�귢�� ...

  6. SpringBoot------连接MySQL报错:The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized

    报错提示: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zon ...

  7. 关于Kafka broker IO的讨论

    Apache Kafka是大量使用磁盘和页缓存(page cache)的,特别是对page cache的应用被视为是Kafka实现高吞吐量的重要因素之一.实际场景中用户调整page cache的手段并 ...

  8. 我的预约订单页面List

    <%@ page language="java" contentType="text/html;charset=UTF-8"%> <%@ ta ...

  9. HTTPS 通讯流程

    原文地址 https://blog.csdn.net/wangweilica6/article/details/50171457 一.简介 前一篇文章,我总结了下,如何部署https服务,开通ssl通 ...

  10. linux下的ssh和rynsc

    在ubuntu下有ssh的目录,但是没有使用 ps -e | grep ssh时没有任何输出,说明没有安装ssh或者是1.x版本,可以打开etc/ssh目录,看是否有文件,下装系统再看看吧.还有ryn ...