Где должны обрабатываться ошибки от вызовов API REST при вызове из действий vuex? - PullRequest
1 голос
/ 23 октября 2019

У меня есть типичный сценарий, когда я вызываю REST API в действиях vuex для извлечения некоторых данных, а затем фиксирую это в мутации. Я использую синтаксис async / await и блоки try / catch / finally. Мой модуль vuex выглядит примерно так:

const state = {
  users: null,
  isProcessing: false,
  operationError: null
}

const mutations = {
  setOperationError (state, value) {
    state.operationError = value
  },
  setIsProcessing (state, value) {
    state.isProcessing = value
    if (value) {
      state.operationError = ''
    }
  },
  setUsers(state, value) {
    state.users= value
  }
}

const actions = {
  async fetchUsers ({ commit }) {
    try {
      commit('setIsProcessing', true)

      const response = await api.fetchUsers()
      commit('setUsers', response.result)
    } catch (err) {
      commit('setUsers', null)
      commit('setOperationError', err.message)
    } finally {
      commit('setIsProcessing', false)
    }
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

Обратите внимание, что я обрабатываю catch(err) { } в действии vuex и не выкидываю эту ошибку. Я просто сохраняю сообщение об ошибке в состоянии и затем связываю его в компоненте vue, чтобы показать его, если operationError верен. Таким образом, я хочу сохранить компонент vue в чистоте от кода обработки ошибок, например, try / catch.

Мне интересно, этот шаблон правильно использовать? Есть ли лучший способ справиться с этим распространенным сценарием? Должен ли я сбросить ошибку в действии vuex и позволить ей распространиться на компонент?

1 Ответ

0 голосов
/ 23 октября 2019

Что я обычно делаю, так это обертка вокруг публикуемых данных, которая обрабатывает запросы API и хранит ошибки. Таким образом, ваш пользовательский объект может записывать ошибки на себя, и вы можете использовать их в компонентах, если они есть.

Например:

import { fetchUsers } from '@\Common\api'
import Form from '@\Utils\Form'

const state = {
  isProcessing: false,
  form: new Form({
    users: null
  })
}

const mutations = {
  setIsProcessing(state, value) {
    state.isProcessing = value
  },
  updateForm(state, [field, value]) {
   state.form[field] = value
  }
}

const actions = {
  async fetchUsers ({ state: { form }, commit }) {
    let users = null
    commit('setIsProcessing', true)

    try {
      users = await form.get(fetchUsers);
    } catch (err) {
      // - handle error
    }

    commit('updateForm', ['users', users])
    commit('setIsProcessing', false)
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

Затем в компоненте, который выможет использовать объект ошибок на обёртке следующим образом:

<template>
  <div>
    <div class="error" v-if="form.erros.has('users')">
      {{ form.errors.get('users') }}
    </div>
    <ul v-if="users">
      <li v-for="user in users" :key="user.id">{{ user.username }}</li>
    </ul>
  </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
  computed: {
    ...mapState('module' ['form']),
    users () {
      return this.form.users
    }
}
</script>

Это мой личный подход, который я считаю очень удобным, и до сих пор он мне очень помог. Не знаю, существуют ли какие-либо стандартные шаблоны или есть явный «правильный способ» сделать это.

Мне нравится подход обертки, потому что тогда ваши ошибки становятся автоматически реагирующими, когда ответ от API возвращаетerror.

Вы можете повторно использовать его вне vuex или даже расширить его и добавить ошибки в заранее определенные границы ошибок, которые действуют как компоненты-оболочки, и использовать методы предоставляют / внедряют, чтобы распространять данные об ошибках по компоненту. дерево и отображать их там, где они вам нужны.

Вот пример компонента границы ошибки:

<template>
  <div>
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    module: {
      type: String,
      required: true,
      validator: function (value) {
        return ['module1', 'module2'].indexOf(value) !== -1
      }
    },
    form: {
      type: String,
      default: 'form'
    }
  },
  provide () {
    return {
      errors: this.$store.state[this.module][this.form].errors
    }
  }
}
</script>

Оберните часть приложения, которая должна получить ошибки:

<template>
  <div id="app">
    <error-boundary :module="module1">
      <router-view/>
    </error-boundary>
  </div>
</template>

Затем вы можете использовать ошибки из оболочки пользователя в дочерних компонентах, например, так:

Если у вас есть глобальная ошибка, например отсутствие ответа от API, и вы хотите отобразить ее на боковой панели ie:

<template>
  <div id="sidebar">
    <div v-if="errors.has('global')" class="error">
      {{ errors.get('global').first() }}
    </div>
    ...
  </div>
</template>
<script>
export default {
  inject: [
    'errors'
  ],
  ...
}
</script>

И тот же объект ошибки повторно используется где-то внутри виджета для ошибки в объекте пользователя validation:

<template>
  <div id="user-list">
    <div v-if="errors.has('users')" class="error">
      {{ errors.get('users').first() }}
    </div>
    ...
  </div>
</template>
<script>
export default {
  inject: [
    'errors'
  ],
  ...
}
</script>

Джеффри Уэй недавно снял сериал на Vue2 и предложил нечто подобное. Вот предложение по объектам Form и Error, на которых вы можете построить: https://github.com/laracasts/Vue-Forms/blob/master/public/js/app.js

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...