Node.js (electron)で作成していたアプリでHTTPリクエスト中の処理をキャンセルして再度リクエストなどする必要があったため、Axiosでリクエスト中の処理をキャンセルする実装をしました。
リクエストを出した側からキャンセルすることができます。
Axios
Axiosはnode.jsとブラウザのためのpromiseベースのHTTPクライアント。
- Axios - GitHub
- ドキュメント axios-http.com
キャンセル処理についてはドキュメントのCancellationに書いてあります。
コードサンプルと解説
ドキュメントのコードサンプルです。
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
// キャンセルのトークン
cancelToken: source.token
}).catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// handle error
}
});
axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
CancelToken.source
を利用してキャンセルトークンを作成してリクエストのオプションに設定します。
そしてsource.cancel()
でリクエストをキャンセルできる。
CancelToken.source()
が返すsource
は独立しているので、▼のようにリクエスト別にキャンセルできます。
// キャンセルトークンが独立している
const source1 = CancelToken.source();
const source2 = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source1.token
})
axios.get('/user/12345', {
cancelToken: source2.token
})
動かして確認してみる
確認しやすいようにドキュメントのコードサンプルを拡張しました。
http://localhost:3000/delay
が時間のかかる処理のエンドポイントとしています。
const axios = require('axios');
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
const source2 = CancelToken.source();
const start = Date.now();
console.log("start: ", start)
// ①レスポンスがそんなかからないリクエスト
axios.get('http://localhost:3000/', {
cancelToken: source.token
}).then((res) => {
// 正常動作
console.log(Date.now() - start, res.data);
}).catch((thrown) => {
if (axios.isCancel(thrown)) {
console.log(Date.now() - start, 'Request canceled: ', thrown.message);
} else {
// handle error
console.log(Date.now() - start, 'Some error: ', thrown.message);
}
})
// ②レスポンスに3秒かかるリクエスト
axios.get('http://localhost:3000/delay', {
cancelToken: source.token
}).then((res) => {
// 正常動作
console.log(Date.now() - start, res.data);
}).catch((thrown) => {
if (axios.isCancel(thrown)) {
console.log(Date.now() - start, 'Request canceled: ', thrown.message);
} else {
// handle error
console.log(Date.now() - start, 'Some error: ', thrown.message);
}
})
// ③レスポンスに3秒かかるリクエスト(キャンセルしない)
axios.get('http://localhost:3000/delay', {
cancelToken: source2.token
})
.then((res) => {
// 正常動作
console.log(Date.now() - start, res.data);
}).catch((thrown) => {
if (axios.isCancel(thrown)) {
console.log(Date.now() - start, 'Request canceled: ', thrown.message);
} else {
// handle error
console.log(Date.now() - start, 'Some error: ', thrown.message);
}
})
// 1秒後にキャンセルリクエスト
setTimeout(() => {
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
}, 1000);
3つのリクエストを用意してキャンセルしています。
- ①レスポンスがそんなかからないリクエスト
- ②キャンセルするレスポンスに3秒かかるリクエスト
- ③キャンセルしないレスポンスに3秒かかるリクエスト
これを実行すると▼のログが出ます。数字はミリ秒です。
> node .\cancellation.js
start: 1630385223319
71 Hello World!
1021 Request canceled: Operation canceled by the user.
3081 3 seconds delay
- ①はキャンセル前にリクエストが終了しているため正常終了。
- ②は3秒かかる処理の途中でキャンセルが実行されたことがわかる。
- ③はキャンセルしたトークンと別のキャンセルトークンが設定されていたため、キャンセルされず正常終了しました。
サーバ側のコード
リクエストキャンセルの確認のためのサーバをExpressで再現しました。
http://localhost:3000/delay
が時間のかかる処理のエンドポイントとしています。
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
// リクエスト返答まで時間がかかるエンドポイント
app.get('/delay', (req, res) => {
setTimeout(()=>{
res.send('3 seconds delay');
}, 3000);
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
コードサンプルはGithubに登録しています。
【Electron】PCのスリープと起動イベントを検知する
ElectronNodejsJavaScriptTypeScriptschedule2021-09-06
axiosでリクエスト中の処理をキャンセルする
JavaScriptNodejsschedule2021-08-31
Node.jsでChrome.exeを起動してページを開く方法
NodejsJavaScriptWindowsschedule2021-08-25