В настоящее время я работаю над проектом по созданию клиента для 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