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. MySql 三大知识点——索引、锁、事务

    1. 索引 索引,类似书籍的目录,可以根据目录的某个页码立即找到对应的内容. 索引的优点:1. 天生排序.2. 快速查找.索引的缺点:1. 占用空间.2. 降低更新表的速度. 注意点:小表使用全表扫描 ...

  2. Tomcat服务器安装、配置、测试

    Tomcat服务器安装.配置.测试(win7_64bit) 目录 1.概述 2.本文用到的工具 3.Tomcat服务器安装配置 4.Tomcat服务器简单测试 5.注意事项 >>看不清的图 ...

  3. 为Sublime Text 设置全局启动快捷键

    为Sublime Text创建快捷方式.找到Sublime Text安装目录中的“sublime_text.exe”文件,然后右击创建快捷方式,如下图:  为Sublime Tex设置全局快捷键.将上 ...

  4. python 信息同时输出到控制台与文件

    python编程中,往往需要将结果用print等输出,如果希望输出既可以显示到IDE的屏幕上,也能存到文件中(如txt)中,该怎么办呢? 方法1 可通过日志logging模块输出信息到文件或屏幕.但可 ...

  5. java模式:建造者模式

    我发现很多源码很喜欢用这个模式,比如spring cloud,spring framework. 建造者模式(Builder)用以构建各种各样的对象,主要功能就是代替对象的构造函数,更加自由化. 举个 ...

  6. NPS - 数字化营销 - 净推荐值

    在获客成本高涨的时代,拥有一批超级用户,让企业更有本钱专注在提升产品及体验,创造更多的超级用户,形成良性循环.超级用户究竟要如何创造?超级用户可以定义成“忠诚用户当中最忠诚的一群人”,因此创造超级用户 ...

  7. Houdini技术体系大纲

    Houdini for UE4 Pipeline的系列教程,前言等想好再写吧

  8. Nginx+Keepalived+Tomcat高可用负载均衡,Zookeeper集群配置,Mysql(MariaDB)搭建,Redis安装,FTP配置

    JDK 安装步骤 下载 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html rpm ...

  9. JavaScript学习历程03

    一闪一闪亮晶晶 <script type="text/javascript"> var nn = Number(prompt('请输入一个1-9的正整数!')); va ...

  10. [转]Visual Studio 2015源文件编码问题(936)

    在Visual Studio中,如果源文件中包含中文,那么当源文件编码为utf8时,会报“C4819 该文件包含不能在当前代码页(936)中表示的字符.请将该文件保存为 Unicode 格式以防止数据 ...