request-promiseは非推奨ですよって話
request-promise
に依存しているrequest
パッケージが非推奨になったことから芋づる式に影響するみたいです。
https://github.com/request/request/issues/3142
fetch使おう
以下のパッケージでfetch
を使います
https://www.npmjs.com/package/node-fetch
タイムアウトするためのざっくりとした流れ
AbortController
という非同期処理を中断させるインターフェースを使用します。
タイムアウトさせたい非同期処理にAbortController
インスタンスのsignal
を渡して、setTimeout()
で指定時間にabort()
を外から呼ぶことで中断させるといった感じです。(Goのcontext
と似てますね)
サンプルうまくいかない問題
READMEの通りLambdaで動かしてみましたが、うまくabort()
が動きませんでした。
npmのサイトには以下のようにバージョンは>= v8.0.0
とあったので、Lambda(nodejs12.x
)でもいけると思ったんですが、、
NOTE: You may cancel streamed requests only on Node >= v8.0.0
const AbortController = require('abort-controller');
const controller = new AbortController();
const timeout = setTimeout(() => {
controller.abort(); // ここが空になる
}, 150);
try {
const response = await fetch('https://example.com', {signal: controller.signal});
const data = await response.json();
} catch (error) {
// errorが空で返るのでAbortErrorを判定できない
if (error instanceof fetch.AbortError) {
console.log('request was aborted');
}
} finally {
clearTimeout(timeout);
}
最終的にLambdaで動いたタイムアウト指定できるfetch
以下のパッケージで生成したAbortController
が動きました
https://www.npmjs.com/package/node-abort-controller
async function postWithTimeout(url, body, ms) {
const fetch = require("node-fetch");
const AbortController = require("node-abort-controller");
const controller = new AbortController();
const timeout = setTimeout(() => {
controller.abort();
}, ms);
const options = {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
signal: controller.signal, // シグナルを渡しておく
};
try {
const response = await fetch(url, options);
const body = await response.json();
return JSON.stringify(body);
} catch (error) {
if (error.type == "aborted") {
console.log("the user aborted a request");
throw new Error(JSON.stringify({ type: "abort" }));
}
throw new Error(JSON.stringify({ type: "other" }));
} finally {
clearTimeout(timeout);
}
}
まとめ
request-promise
からの切り替えをお考えのあなたに向けたfetchな記事になれば幸いです