代码之家  ›  专栏  ›  技术社区  ›  Daniel Park

从Vuex操作返回承诺

  •  170
  • Daniel Park  · 技术社区  · 8 年前

    从概念上讲,Vuex对我来说是一种范式转变,但我相信我现在知道它的全部内容,并完全理解它!但存在一些小的灰色区域,主要是从实现的角度来看。

    我觉得这个设计不错,但不知道是否与Vuex相矛盾 cycle 单向数据流。

    基本上,从一个动作返回一个promise(-like)对象被认为是一个好的实践吗?我将它们视为异步包装器,具有失败等状态,因此似乎很适合返回承诺。相反,变异体只是改变事物,是存储/模块中的纯结构。

    5 回复  |  直到 8 年前
        1
  •  311
  •   Mani    7 年前

    actions 在Vuex中是异步的。让调用函数(动作的发起方)知道动作已完成的唯一方法是返回一个承诺并稍后解析它。

    下面是一个例子: myAction 返回 Promise 许诺 稍后-全部异步

    actions: {
        myAction(context, data) {
            return new Promise((resolve, reject) => {
                // Do something here... lets say, a http call using vue-resource
                this.$http("/api/something").then(response => {
                    // http success, call the mutator and change something in state
                    resolve(response);  // Let the calling function know that http is done. You may send some data back
                }, error => {
                    // http failed, let the calling function know that action did not work out
                    reject(error);
                })
            })
        }
    }
    

    ,它将获得这个Promise对象,并可以知道它是否成功。以下是Vue组件的一些示例代码:

    export default {
        mounted: function() {
            // This component just got created. Lets fetch some data here using an action
            this.$store.dispatch("myAction").then(response => {
                console.log("Got some data, now lets show something in this component")
            }, error => {
                console.error("Got nothing from server. Prompt user to check internet connection and try again")
            })
        }
    }
    

    正如您在上面看到的,这对 行动 退回 许诺 否则,动作发起人无法知道正在发生什么以及何时事情足够稳定以在用户界面上显示某些东西。

    最后一点注意: mutators -正如你正确指出的,它们是同步的。他们在 state 行动 .不需要混合 Promises 具有 突变子 ,作为 行动 处理好那部分。

    编辑:我对单向数据流Vuex循环的看法:

    如果您访问以下数据: this.$store.state["your data key"] 在组件中,数据流是单向的。

    动作的承诺只是让组件知道动作已经完成。

    $store.state["your data key"] 其是单向的并且遵循vuex数据生命周期。

    以上段落假设您的mutator使用 Vue.set(state, "your data key", http_data) ,一旦http调用在操作中完成。

        2
  •  55
  •   Anoop Thiruonam    2 年前

    关于一个封闭主题的信息: 您不必创建承诺,axios会自己返回一个承诺:

    裁判: https://forum.vuejs.org/t/how-to-resolve-a-promise-object-in-a-vuex-action-and-redirect-to-another-route/18254/4

    例子:

        export const loginForm = ({ commit }, data) => {
          return axios
            .post('http://localhost:8000/api/login', data)
            .then((response) => {
              commit('logUserIn', response.data);
            })
            .catch((error) => {
              commit('unAuthorisedUser', { error:error.response.data });
            })
        }
    

        addEmployee({ commit, state }) {       
          return insertEmployee(state.employee)
            .then(result => {
              commit('setEmployee', result.data);
              return result.data; // resolve 
            })
            .catch(err => {           
              throw err.response.data; // reject
            })
        }
    

    异步等待

        async getUser({ commit }) {
            try {
                const currentUser = await axios.get('/user/current')
                commit('setUser', currentUser)
                return currentUser
            } catch (err) {
                commit('setUser', null)
                throw 'Unable to fetch current user'
            }
        },
    
        3
  •  8
  •   Bhaskararao Gummidi    6 年前

    ADD_PRODUCT : (context,product) => {
      return Axios.post(uri, product).then((response) => {
        if (response.status === 'success') {  
          context.commit('SET_PRODUCT',response.data.data)
        }
        return response.data
      });
    });
    

    组成部分

    this.$store.dispatch('ADD_PRODUCT',data).then((res) => {
      if (res.status === 'success') {
        // write your success actions here....
      } else {
         // write your error actions here...
      }
    })
    
        4
  •  1
  •   srmico    5 年前

    仅在必要时从您的操作中返回承诺,但对相同的操作进行干链接。

    长期以来,我也认为返回操作与单向数据流的Vuex循环相矛盾。

    但是,有 边缘案例 在那里,从你的行动中返回承诺可能是“必要的”。

    想象一种情况,一个动作可以由两个不同的组件触发,每个组件处理故障情况的方式不同。 在这种情况下,需要将调用方组件作为参数传递,以便在存储中设置不同的标志。

    用户可以在导航栏和/配置文件页面(包含导航栏)中编辑用户名的页面。两者都触发“更改用户名”操作,这是异步的。

    当然,这是一个愚蠢的例子,但我看不到解决这个问题的方法,不需要重复代码并在两个不同的操作中进行相同的调用。

        5
  •  -2
  •   Chris Michael    5 年前

    actions.js

    const axios = require('axios');
    const types = require('./types');
    
    export const actions = {
      GET_CONTENT({commit}){
        axios.get(`${URL}`)
          .then(doc =>{
            const content = doc.data;
            commit(types.SET_CONTENT , content);
            setTimeout(() =>{
              commit(types.IS_LOADING , false);
            } , 1000);
          }).catch(err =>{
            console.log(err);
        });
      },
    }
    

    home.vue

    <script>
      import {value , onCreated} from "vue-function-api";
      import {useState, useStore} from "@u3u/vue-hooks";
    
      export default {
        name: 'home',
    
        setup(){
          const store = useStore();
          const state = {
            ...useState(["content" , "isLoading"])
          };
          onCreated(() =>{
            store.value.dispatch("GET_CONTENT" );
          });
    
          return{
            ...state,
          }
        }
      };
    </script>