美文网首页
为什么要用Action管理异步操作

为什么要用Action管理异步操作

作者: 指尖跳动 | 来源:发表于2019-06-13 21:25 被阅读0次

    Action 类似于 mutation,不同在于:

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

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

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

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

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

    // mutation.js
    const increment = (state) => {
      setTimeout(() => {
        state.count++
      }, 1000)
    }
    const decrement = (state) => {
      setTimeout(() => {
        state.count--
      }, 2000)
      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的代码改回来)

    
    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')
      }, 1000)
    }
    let decrementAsync = (content) => {
      setTimeout(() => {
        content.commit('decrement')
      }, 1000)
    }
    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的结果一毛一样。再看一下官网说明。



    所以,官网说的这句话有问题?其实官网给了说明。


    下面来看一个复杂的例子,这个例子有助于理解为什么要用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

    下面我们重写一下代码

    // Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象
    let incrementAsync = (content) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          content.commit('increment')
          resolve()
        }, 1000)
      })
    }
    let decrementAsync = (content) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          content.commit('decrement')
          resolve()
        }, 1000)
      })
    }
    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管理异步操作

          本文链接:https://www.haomeiwen.com/subject/ksmefctx.html