отклоненное HTTP-обещание не попадает в блок catch

#javascript #vue.js #axios

#javascript #vue.js #axios

Вопрос:

Я использую VueJS (и Vuex) с Axios для связи с Express Api. Я могу удалить свою собственную учетную запись пользователя, использующую сервис

 import api from '@/services/api.js';

export default {
  deleteAccount: () => api().delete('/users')
};
  

где api находится axios экземпляр. Мне не нужно передавать идентификатор пользователя, потому что api идентифицирует пользователя по токену.

В моем представлении настроек я могу использовать эту услугу

 <script>
import { mapActions } from 'vuex';

import UserService from '@/services/users'; 

export default {
  name: 'Settings',
  methods: {
    ...mapActions('alert', [
      'showSuccessAlert',
      'showErrorAlert'
    ])
    deleteAccount: async function() {
      try {
        await UserService.deleteAccount();

        this.showSuccessAlert({ message: 'Account was deleted successfully' });
        // other stuff
      } catch (error) {
        this.showErrorAlert({ message: error.message });
      }
    }
  }
};
</script>
  

Вызов UserService.deleteAccount() возвращает мне ожидающее обещание. Использование await возвращает мне ответ api.

В настоящее время api всегда возвращает a 500 для целей тестирования. Я думал, что если обещание будет отклонено, код всегда будет переходить непосредственно в блок catch. Здесь код возвращает отклоненное обещание (и записывает «Внутреннюю ошибку сервера» в консоль, но передает и показывает предупреждение об успешном завершении / никогда не выполняет код из блока catch.

Что не так с кодом? Я неправильно понял обещания?


Обновить

Мой экземпляр axios

 import axios from 'axios';

import TokensService from '@/services/tokens.js';
import store from '@/store/store.js';

function getTokenString() {
  return `Bearer ${TokensService.getToken()}`;
}

export default () => {
  const instance = axios.create({
    baseURL: 'http://localhost:3000/',
    headers: {
      'Content-Type': 'application/json',
      Authorization: getTokenString(),
    },
  });

  instance.interceptors.request.use((config) => {
    config.headers.Authorization = getTokenString();
    return config;
  }, (err) => Promise.reject(err));

  instance.interceptors.response.use((res) => res, (err) => {
    if (err.response.status === 401) {
      store.dispatch('authentication/destroySession');
      store.dispatch('alert/showErrorAlert', { message: err.message });
    }

    return err;
  });

  return instance;
};
  

Вызов api().delete() такой же, как axios.delete('http://localhost:3000/users')

Комментарии:

1. returns a 500 — статус http не обязательно означает отклоненное обещание — браузеры fetch , например, не отклоняют запрос 500, или 404, или любой успешный (до получения ответа http) запрос

2. Возвращает ли код состояния 500 автоматически отклоняет обещание?

3. да, обычно это так

4. как выглядит код для api().delete ? это ваш код?

5. насколько я знаю, все «неудачные запросы» будут переходить в блок catch

Ответ №1:

попробуйте вернуть отклоненное обещание здесь

   instance.interceptors.response.use((res) => res, (err) => {
    if (err.response.status === 401) {
      store.dispatch('authentication/destroySession');
      store.dispatch('alert/showErrorAlert', { message: err.message });
    }

    return Promise.reject(err);
  });
  

согласно примерам https://github.com/axios/axios#interceptors

Комментарии:

1. о да, мне пришлось изменить return err; на return Promise.reject(err);