私は現在、UdemyインストラクターAPIのクライアントを作成するプロジェクトに取り組んでいます。
HTTPクライアントとしてAxiosを使用して、Vueでクライアントを作成しました。
さまざまなAPIリクエストをES6化されたAPIラッパーライブラリ(Udemy.js
)の関数に抽象化して、簡単に再利用できるようにしました。
Udemy.js
最初にAxiosのインスタンスを初期化し、次にそのインスタンスをベースとして使用するAPI関数をpromiseとしてエクスポートします。
以下はファイルから抜粋したものですが、読みやすくするためにモジュールがエクスポートする関数の1つを除いてすべて削除しました(そして明らかに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コンポーネントに取り込むにはどうすればよいですか?
編集(2月6日)
私は最初の投稿にすべての便利なコンソール出力を含めなかったので、ここにあります。実行されるconsole.log()行はケース2行です(ケース3の場合のように、プレフィックスが「エラー:」ではなく、コンソールログエントリが1つだけ追加されます)。
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(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(1月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(2月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
したがって、実際には、呼び出していたAPIがエラー応答で正しいCORSヘッダーを提供しなかった結果であると思われる答えです(したがって、CORSは2xx応答に対してのみ許可されていました)。
その結果、Axiosは応答にアクセスできませんでした。
今のところ、一般的なあいまいなエラーを回避する必要がありますが、今後の解決策は、成功とエラー応答の両方でCORSを提供するAPIの開発者にあります。
ベルギの助けに感謝します。それが最終的に私を問題の原因に導きました。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加