如何将 AXIOS 请求与 Vuex 存储区分开

How to separate AXIOS requests from a Vuex store

我有一个非常正常的 Vuex 存储文件 这是代码:

//store.js
import Vue from 'vue';
import Vuex from 'vuex';


Vue.use(Vuex);

export const store = new Vuex.Store({
  state: {
    loading: true,
    companyBasicInfo: [

    ]
  },
  mutations: {
    getCompanyBasicInfo: (state, res) => {
      state.companyBasicInfo.push(res);
    },
    changeLoadingStatue: (state, loading) => {
      state.loading = loading;
    }
  },
  actions: {
    getCompanyBasicInfo: context => {
// HERE IS MY AXIOS REQUESTS
    }
  }
});

我正在 getCompanyBasicInfo() 操作中编写我的 axios 请求并且一切正常。

我想做什么

在另一个文件中分离我的 AXIOS 请求,然后在我的 store.js 文件中调用它们只是为了减少我的 store.js 文件..

我试过的

我尝试创建名为 requests.js 的文件并在其中写入以下代码:

import axios from 'axios';

export default GET_COMPANY_DETAILS = () => {
  setTimeout(() => {
    axios.get('http://localhost:3000/companies/show/trade key egypt').then((res) => {
      context.commit('getCompanyBasicInfo', res.data);
      context.commit('changeLoadingStatue', false);
    }).catch(e => {
      console.log(e);
    });
  }, 3000);
};

然后尝试将它们导入我的 store.js 文件

import requests from './requests';

问题

每当我尝试在 getCompanyBasicInfo() 操作中写入 requests.GET_COMPANY_DETAILS(); 时,我都无法访问 requests.js 文件中的方法。

错误我得到

Uncaught ReferenceError: GET_COMPANY_DETAILS is not defined 在控制台中

导出问题

由于您使用的是 export default GET_COMPANY_DETAILS,当您导入 requests 时,它是 GET_COMPANY_DETAILS 函数。

所以你可以直接调用 requests()

查看 MDN documentation on export 以查看所有可能性。

如何导出 API

也就是说,导出 API 的正确方法是:

// api.js
import axios from 'axios';

// create an axios instance with default options
const http = axios.create({ baseURL: 'http://localhost:3000/' });

export default {
    getCompanyDetails(tradeKey) {
        // then return the promise of the axios instance
        return http.get(`companies/show/${tradeKey}`)
            .catch(e => {
                // catch errors here if you want
                console.log(e);
            });
    },
    anotherEndpoint() {
        return http.get('other/endpoint');
    }
};

您可以像我一样导出 default API,甚至可以同时导出命名导出和默认导出。

export function getCompanyDetails(tradeKey){ /*...*/ }
export default { getCompanyDetails }

然后,在您的商店中:

import api from './api';

// ...

actions: {
    getCompanyBasicInfo({ commit }, key) {
        // It's important to return the Promise in the action as well
        return api.getCompanyDetails(key).then(({ data }) => {
            commit('getCompanyBasicInfo', data);
            commit('changeLoadingStatue', false);
        });
    }
}

商店相关代码仍然需要在您的操作中。

进一步隔离

我写了 an answer with examples on axios-middleware and axios-resource 来帮助创建单一责任模块。

您可以在中间件中处理错误,同时将端点配置集中在资源中 类。

我建议您根据 Vuex 文档中建议的 application structure 来构建您的代码。

这将使您很好地分离关注点,并使您的 store.js 漂亮而精简。

然后,导出函数而不是默认导出。将来,您可能希望从 requests.js.

导出多个函数

例如

import axios from 'axios';

export function getCompanyDetails() {
  setTimeout(() => {
    axios.get('http://localhost:3000/companies/show/trade key egypt').then((res) => {
      context.commit('getCompanyBasicInfo', res.data);
      context.commit('changeLoadingStatue', false);
    }).catch(e => {
      console.log(e);
    });
  }, 3000);
};

export function someOtherApiMethod() {}

然后,而不是在 GET_COMPANY_DETAILS 中使用 setTimeout,return 来自 Axios 本身的承诺。

例如

 export function getCompanyDetails() {
    return axios
        .get('http://localhost:3000/companies/show/trade key egypt')
        .then(res => res.data)
};

然后,在你的行动中使用承诺

import { getCompanyDetails } from './requests';

actions: {
    getCompanyBasicInfo: context => {
        getCompanyDetails().then(() => {
            // commit your mutations
        });
    }
  }