0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Node.js】Lambdaでタイムアウト指定できるfetch

Last updated at Posted at 2021-01-28

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な記事になれば幸いです

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?