Почему мой экземпляр Axios не возвращает ответ в обнаруженной ошибке? - PullRequest
0 голосов
/ 05 февраля 2019

В настоящее время я работаю над проектом по созданию клиента для API инструктора Udemy.

Я написал клиент на Vue, используя Axios в качестве HTTP-клиента.

Я абстрагировал различные запросы API в функции в библиотеке-оболочке API с интерфейсом ES6 (Udemy.js), чтобы их можно было легко использовать повторно.

Udemy.js сначала инициализирует экземплярЗатем Axios экспортирует функции API, которые используют этот экземпляр в качестве базы в качестве обещаний.

Ниже взято из файла, хотя я удалил все, кроме одной, функции, экспортируемые модулем для удобства чтения (и, очевидно, отредактированмаркер API).URI конечной точки содержит «message-threadssss» - это преднамеренно, чтобы заставить сервер вернуть 404:

import axios from 'axios';

const token = '***************************';
const axiosOptions = {
  baseURL: 'https://www.udemy.com/instructor-api/v1',
  timeout: 10000,
  headers: {
    Accept: '*/*',
    'Content-Type': 'application/json;charset=utf-8',
    Authorization: `Bearer ${token}`,
  },
};

const axiosInstance = axios.create(axiosOptions);

export default {
  postMessage(messageThreadId, messageBody) {
    return axiosInstance
            .post(`/message-threadssss/${messageThreadId}/messages/`, {
              content: messageBody,
            })
            .then(response => response.data)
            .catch(error => error);
  },
}

UdemyApi.postMessage(threadId, threadReply);
.then((response) => {
        this.isLoading = false;
        this.sentReply = response;
        this.replyBody = '';
        this.$root.$emit('reply-sent', {
          threadId: this.thread.id,
          sentReply: this.sentReply,
        });
      })
      .catch((error) => {
        if (error.response) {
          // Case 1 (Server returned error)
          console.log(error.response.data);
          console.log(error.response.status);
          console.log(error.response.headers);
        } else if (error.request) {
          // Case 2 (Pre-response error)
          console.log(error.request);
        } else {
          // Case 3 (Mysterious error)
          console.log('Error:', error.message);
        }
        this.$root.$emit('show-snackbar', {
          message: `Failed to send. ${error} `,
          actionText: 'Understood. :(',
        });
        this.isLoading = false;
      });

Запрос отправляется без проблем, и, если запрос выполнен успешно (т.е. 2xx), компонент Vue может получить доступ к данным ответа в блоке then().

Когда сервер возвращает ошибку (404 в данном случае), я ожидаю, что обнаруженная ошибка будет содержать объект response (случай 1).

Вместо этого, нет response объект возвращается с ошибкой (случай 2), которая мешает мне правильно его обработать.Это происходит, когда запрос заставляет сервер ответить 404 ошибкой:

HTTP/2.0 404 Not Found
content-type: text/json

Я читал, что если к Axios применены перехватчики, это может привести к этой проблеме, но в этом случае,Я не применял никаких перехватчиков.

В общем, я немного растерялся.Как получить ответ сервера в мой компонент Vue?

Редактировать (6 февраля)

Я не включил полезный вывод консоли в свой первый поствот так вот.Выполненная строка console.log () - это строка Case 2 (добавлена ​​только одна запись журнала консоли, без префикса «Error:», как в случае 3):

12:22:28.748
XMLHttpRequest
    mozAnon: false
    mozSystem: false
    onabort: null
    onerror: function handleError()
    onload: null
    onloadend: null
    onloadstart: null
    onprogress: null
    onreadystatechange: function handleLoad()
    ontimeout: function handleTimeout()
    readyState: 4
    response: ""
    responseText: ""
    responseType: ""
    responseURL: ""
    responseXML: null
    status: 0
    statusText: ""
    timeout: 100000
    upload: XMLHttpRequestUpload { onloadstart: null, onprogress: null, onabort: null, … }
    withCredentials: false
    <prototype>: XMLHttpRequestPrototype { open: open(), setRequestHeader: setRequestHeader(), send: send(), … }
replybox.vue:72

Редактировать 2 (6 февраля)

Если я уберу then() и catch() из определения postMessage(), чтобы он выглядел следующим образом:

 postMessage(messageThreadId, messageBody) {
    return axiosInstance
            .post(`/message-threadssss/${messageThreadId}/messages/`, {
              content: messageBody,
            });
  },

И затемупростите блок catch() вызова postMessage(), чтобы просто вывести объект error, чтобы он выглядел следующим образом:

    .catch((error) => {
        console.log(error);
        this.$root.$emit('show-snackbar', {
          message: `Failed to send. ${error} `,
          actionText: 'Understood. :(',
        });
        this.isLoading = false;
      });

Вывод на консоль:

12:38:51.888 Error: "Network Error"
    createError webpack-internal:///./node_modules/axios/lib/core/createError.js:16:15
    handleError webpack-internal:///./node_modules/axios/lib/adapters/xhr.js:87:14
replybox.vue:62

Правка 3 (6 января)

Я понял, что в моем предыдущем редактировании я пропустил вывод error.request после того, как удалил .then и .catch из своего определения postMessage.Если я повторно добавлю console.log(error.request); к блоку .catch вызова в моем компоненте, это будет вывод:

12:58:55.436
XMLHttpRequest
    mozAnon: false
    mozSystem: false
    onabort: null
    onerror: function handleError()
    onload: null
    onloadend: null
    onloadstart: null
    onprogress: null
    onreadystatechange: function handleLoad()
    ontimeout: function handleTimeout()
    readyState: 4
    response: ""
    responseText: ""
    responseType: ""
    responseURL: ""
    responseXML: null
    status: 0
    statusText: ""
    timeout: 100000
    upload: XMLHttpRequestUpload { onloadstart: null, onprogress: null, onabort: null, … }
    withCredentials: false
    <prototype>: XMLHttpRequestPrototype { open: open(), setRequestHeader: setRequestHeader(), send: send(), … }

Редактировать 4 (6 февраля)

Чтобы подтвердить или исключить мою реализацию моего уровня абстракции API, я непосредственно вызвал экземпляр Axios в моем компоненте:

const token = '*********************';
const axiosOptions = {
  baseURL: 'https://www.udemy.com/instructor-api/v1',
  timeout: 100000,
  headers: {
    Accept: '*/*',
    'Content-Type': 'application/json;charset=utf-8',
    Authorization: `Bearer ${token}`,
  },
};
const axiosInstance = axios.create(axiosOptions);
axiosInstance
.post(`/message-threadssss/${this.thread.id}/messages/`, {
  content: this.replyBody,
})
.then((response) => {
  this.isLoading = false;
  this.sentReply = response;
  this.replyBody = '';
  this.$root.$emit('reply-sent', {
    threadId: this.thread.id,
    sentReply: this.sentReply,
  });
})
.catch((error) => {
  console.log('Error obj: ', error);
  console.log('Request error obj: ', error.request);
  this.$root.$emit('show-snackbar', {
    message: `Failed to send. ${error} `,
    actionText: 'Understood. :(',
  });
  this.isLoading = false;
  this.axiosResult = error;
});

Как и прежде, сервер вернул ожидаемое значение 404, а .catchБлок в моем компоненте перехватил ошибку.

Как и раньше, ответ от перехваченной ошибки отсутствовал

13:25:45.783 Error obj:  Error: "Network Error"
    createError webpack-internal:///./node_modules/axios/lib/core/createError.js:16:15
    handleError webpack-internal:///./node_modules/axios/lib/adapters/xhr.js:87:14
replybox.vue:79

13:25:45.786 Request error obj:  
XMLHttpRequest
    mozAnon: false
    mozSystem: false
    onabort: null
    onerror: function handleError()
    onload: null
    onloadend: null
    onloadstart: null
    onprogress: null
    onreadystatechange: function handleLoad()
    ontimeout: function handleTimeout()
    readyState: 4
    response: ""
    responseText: ""
    responseType: ""
    responseURL: ""
    responseXML: null
    status: 0
    statusText: ""
    timeout: 100000
    upload: XMLHttpRequestUpload { onloadstart: null, onprogress: null, onabort: null, … }
    withCredentials: false
    <prototype>: XMLHttpRequestPrototype { open: open(), setRequestHeader: setRequestHeader(), send: send(), … }
replybox.vue:80

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Итак, похоже, что ответ на самом деле был результатом того, что API, который я вызывал, не обслуживал правильные заголовки CORS с ответами об ошибках (поэтому CORS был разрешен только для ответов 2xx).

Следовательно, Axios не удалось получить доступ к ответу.

На данный момент мне нужно обойти общую неоднозначную ошибку, но решение в будущем лежит на разработчиках API, обслуживающих CORS скак успешные, так и ошибочные ответы.

Большое спасибо Берги за помощь, которая в конечном итоге привела меня к причине проблемы.

0 голосов
/ 05 февраля 2019

Я почти уверен, что все, что вам нужно сделать, это удалить .then и .catch из вашей функции postMessage, и вы должны быть готовы пойти

postMessage(messageThreadId, messageBody) {
  return axiosInstance
     .post(`/message-threadssss/${messageThreadId}/messages/`, {
        content: messageBody,
      })
}

Таким образом, postMessage возвращает обещание.А когда вы на самом деле звоните postMessage, вы можете использовать .then и .catch

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