Mi solución actual funciona: obtengo los datos de la API. Pero a Vue no le gusta.
Salida de la consola a continuación: 
¿Cuál es la forma correcta de usar setInterval dentro de la tienda Vuex sin "mutar el estado de la tienda vuex fuera de los controladores de mutación"?
En Index.vue :
mounted () { store.dispatch('setAPIEndpoint', { endpoint: 'chillersystem', requestType: 'post', payload: {}, }) }, En actions.js :
async setAPIEndpoint ({ commit }, payload) { commit('SET_API_ENDPOINT', payload) } En mutations.js :
SET_API_ENDPOINT (state, payload) { // Clear the previous interval to prevent a memory leak if (state.api.interval !== null) { state.api.interval = null state.api.data = {} } // Reset the API parameters state.api.endpoint = payload.endpoint state.api.requestType = payload.requestType state.api.payload = payload.payload // Schedule repetition state.api.interval = setInterval(() => { if (state.api.requestType === 'post') { axios.post(`/api/${ state.api.endpoint }`, state.api.payload) .then((response) => { state.api.data = response.data }) .catch((error) => { process.env.NODE_ENV === 'production' ? location.href = 'pages/error-500/' : console.log(error) }) } }, state.api.refreshTimer) } En state.js
const state = { api: { endpoint: '', requestType: '', payload: {}, data: {}, refreshTimer: 5000, // Milli-seconds interval: null } }Las mutaciones deben ejecutarse sincrónicamente
Haga su trabajo asíncrono en acción en lugar de mutación
No es la mejor implementación, pero obtendrá una idea de cómo abordarla a partir del código a continuación.
//mutations.js SET_API_ENDPOINT(state, payload) { // Clear the previous interval to prevent a memory leak if (state.api.interval !== null) { state.api.interval = null state.api.data = {} } // Reset the API parameters state.api.endpoint = payload.endpoint state.api.requestType = payload.requestType state.api.payload = payload.payload state.api.interval = payload.interval state.api.data = payload.data } //actions.js: async setAPIEndpoint({ commit, state }, payload) { const endpoint = payload.endpoint; const requestType = payload.requestType; const payload = payload.payload; let data = null; let interval = null; const getData = () => { return new Promise((resolve, reject) => { interval = setInterval(() => { if (requestType === 'post') { axios.post(`/api/${endpoint}`, payload) .then((response) => { data = response.data; resolve(); }) .catch((error) => { process.env.NODE_ENV === 'production' ? location.href = 'pages/error-500/' : console.log(error) reject(); }) } } , state.api.refreshTimer); }) }; await getData(); const newPayload = { ...payload, data, interval } commit('SET_API_ENDPOINT', newPayload) }Esta respuesta se basa en la de @Abdullah Khan. Consúltelo para obtener contexto adicional.
A continuación se muestra una solución implementable para cualquiera que llegue aquí desde Google con un caso de uso similar.
En su componente Vue que necesita actualizar la API, llame a continuación desde un gancho de método/ciclo de vida:
await this.$store.dispatch('setAPI', { requestEndpoint: '/api/endpoint', requestType: 'get', requestPayload: {} }) En actions.js :
import axios from '../axios' const actions = { clearAPI ({ commit }) { commit('CLEAR_API') }, async setAPI ({ commit, state }, payload) { commit('CLEAR_API') const requestEndpoint = payload.requestEndpoint const requestType = payload.requestType const requestPayload = payload.requestPayload let data = null const getData = () => { return new Promise((resolve, reject) => { if (requestType === 'get') { axios.get(requestEndpoint, requestPayload) .then((response) => { data = response.data const newPayload = { requestEndpoint, requestType, requestPayload, data } commit('SET_API_DATA', newPayload) resolve() }) .catch((error) => { process.env.NODE_ENV === 'production' ? location.href = 'pages/error-500/' : console.log(error) reject() }) } }) } await getData() const interval = setInterval(() => { getData() }, state.api.pollTimer) commit('SET_API_INTERVAL', interval) } } En mutations.js :
const mutations = { CLEAR_API (state) { // If interval exists, clear it if (state.api.interval) { clearInterval(state.api.interval) } // Clear the API parameters state.api.requestEndpoint = null state.api.requestType = null state.api.requestPayload = null state.api.data = {} }, SET_API_DATA (state, payload) { // Set the API parameters state.api.requestEndpoint = payload.requestEndpoint state.api.requestType = payload.requestType state.api.requestPayload = payload.requestPayload state.api.data = payload.data }, SET_API_INTERVAL (state, interval) { // If interval exists, clear it if (state.api.interval) { clearInterval(state.api.interval) } // Set the API Interval state.api.interval = interval } } En state.js :
const state = { api: { requestEndpoint: null, requestType: null, requestPayload: null, data: {}, interval: null, pollTimer: 5000 // Milli-seconds }, }