axios でのリクエストのキャンセルは、 1: リクエストの後に同じリクエストをキャンセルする 2: リクエストの前に同じリクエストをキャンセルする
## リクエストの後に同じリクエストをキャンセルする:
axios を使用してリクエストを送信する場合、リクエストが連続して送信される場合短期間 同じリクエストに対して、リクエスト結果に混乱が生じたり、応答が繰り返されたりする可能性があります。この状況を回避するには、axios のキャンセルリクエスト機能を使用して、各リクエストを送信する前に前のリクエストをキャンセルします。axios を使用してリクエストをキャンセルするサンプル コードを次に示します。
import axios from 'axios';
// 创建一个 CancelToken 对象
const source = axios.CancelToken.source();
// 发送请求
axios.get('/api/data', {
// 将 cancelToken 属性设置为上面创建的 CancelToken 实例
cancelToken: source.token
}).then(response => {
console.log(response.data);
}).catch(error => {
console.error(error);
});
// 取消之前的请求
source.cancel('Duplicate request');
上記のコードでは、最初に CancelToken オブジェクト ソースを作成し、それをリクエストの cancelToken 属性に渡します。その後、前のリクエストをキャンセルする必要がある場合は、source.cancel() メソッドを呼び出すだけです。この時点では、応答の重複を避けるために、後続のリクエストは送信されません。
なお、リクエストがキャンセルされる前にリクエストの送信と応答が成功した場合、成功したリクエストの結果はキャンセルできないため、成功したリクエストの結果も処理する必要があります。さらに、エラーを避けるために、リクエストがキャンセルされたときの例外も処理する必要があります。
##このリクエストの前に同じリクエストをキャンセルします:
axios では、最後のリクエストをキャンセルすることと、以前のすべてのリクエストをキャンセルすることには違いがあります。前のリクエストをキャンセルするには、現在のリクエストの cancelToken を記録し、次のリクエストの前にキャンセル リクエスト オペレーションを送信します。以前のリクエストをすべてキャンセルするには、リクエスト キューを維持し、新しいリクエストが開始される前に以前のリクエストをすべてキャンセルする必要があります。
以前のリクエストをすべてキャンセルする例を次に示します。
import axios from 'axios';
// 创建一个请求队列
let pending = [];
const CancelToken = axios.CancelToken;
const removePending = (config) => {
for (let p in pending) {
if (pending[p].url === config.url + '&' + config.method) {
pending[p].cancel("request canceled");
pending.splice(p, 1);
}
}
}
// 添加请求拦截器
axios.interceptors.request.use(
(config) => {
removePending(config);
config.cancelToken = new CancelToken((c) => {
pending.push({ cancel: c, url: config.url + '&' + config.method });
});
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器
axios.interceptors.response.use(
(response) => {
removePending(response.config);
return response;
},
(error) => {
return Promise.reject(error);
}
);
上記のコードでは、保留中のリクエスト キューを作成し、次に cancelToken をリクエスト設定に追加してリクエスト キューにプッシュします。新しいリクエストを送信する前に、リクエスト キューを走査し、以前のリクエストをすべてキャンセルして、リクエスト キューから削除します。同時に、応答インターセプターの要求キューから完了した要求を削除する必要もあります。
jsonp を使用して送信されたリクエストなど、送信されたリクエストがキャンセルできない場合、上記のコードはそのようなリクエストをキャンセルできないことに注意してください。したがって、実際の状況に応じて適切なキャンセル方法を選択する必要があります。
###キャンセル後に再度リクエストを送信する際にキャンセルを求められた場合はどうすればよいですか?
axios でリクエストがキャンセルされた場合、同じリクエストを再度送信すると、「キャンセルはキャンセルされました」というエラーが表示されます。これは、axios への同じリクエストがキャンセルされたため、再度送信することができないためです。同じリクエストを再度送信する必要がある場合は、新しい cancelToken を作成する必要があります。作成しないと、常にキャンセルするように求められます。
cancelToken を再作成するサンプル コードを次に示します。
import axios from 'axios';
let cancelToken = axios.CancelToken;
let cancel;
let config = {
method: 'get',
url: '/api/data',
cancelToken: new cancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c;
})
};
// 添加请求拦截器
axios.interceptors.request.use(
(config) => {
// 如果 cancel 存在说明上次请求被取消了,重新创建一个
if (typeof cancel === 'function') {
config.cancelToken = new cancelToken(function executor(c) {
cancel = c;
});
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 发送请求
axios(config)
.then((response) => {
console.log(response);
})
.catch((error) => {
if (axios.isCancel(error)) {
console.log('Request canceled', error.message);
} else {
console.log(error);
}
});
// 取消请求
cancel();
上記のコードでは、リクエストを送信する前に cancelToken を作成し、キャンセル関数を保存します。リクエストを送信するときに、cancel 関数が存在するかどうかを確認します。存在する場合は、最後のリクエストがキャンセルされたことを意味するため、cancelToken を再作成して新しいリクエストに渡す必要があります。これにより、キャンセルした後に同じリクエストを再送信することができます。
axios は XHR オブジェクトのカプセル化であるため、リクエストが送信され、サーバーがリクエストを受信した場合、cancelToken が abort() メソッドを呼び出してリクエストをキャンセルすると、データの一部が送信されてしまう可能性があります。したがって、使用には注意が必要です。
真のキャンセルを実現できるのはフェッチ リクエストのみです。!!