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