Posted at

JavaScriptのsetTimeoutで指定できる時間には限界値があるって話


setTimeoutの挙動がおかしい

setTimeoutで指定した時間が経過したら、関数を発火させたいって話があったんすよ。(setTimeoutなんだから当たり前感)

それで頼まれた通り実装したら、、、、なんやこれ、引数によって挙動が違うやんけ


そのときの状況

○秒経過したら〜とか、○分経過したら〜とかそんな可愛らしいもんじゃなくて、数日単位で経過時間を指定してました。数が大きいものだと2週間とか1ヶ月とか。それに加えてsetTimeoutの引数ってミリ秒単位で指定しないといけないから引数がでかいことでかいこと


で、原因は引数が大きすぎたってこと

まんまやんけ!みたいなね、仕方ないじゃん、本当にそうなんだもん。

これは私の推測なんだけど、setTimeoutの引数には32bit符号付き整数の最大値までしか設定できないんだと思う。具体的な数字で表すと、2,147,483,647までです。実際、この21億なんちゃらまではきちんと動いていたものの、これよりたった1増えただけの2,147,483,648だとすぐおかしな挙動(=指定時間を経過していないのに発火)しだすもん。


もう少し賢そうな感じで書くと

桁あふれだっけ?多分その辺なんだと思う。1増えた瞬間いろいろ起きて2進数上の表記だと負の数になっちゃうみたいなやつ。その現象が起きてるから、引数に負の数が設定されたと思われる=すぐ発動しちゃうってことだったんだと思う。つーか誰か1人ぐらいこの話書いといてくれたっていいじゃんって思ったからワシが書く、手柄は自分のものにするスタイル


余談

大学で数値計算の授業を受けていた時に、教授が散々この話をしていたな〜と思ってなんとなく実験したらビンゴ!

JSで扱える数値に関して詳しい方がいらっしゃったら教えてください。