36. fake timer(setTimeout)を実装する

JavaScript

少し工夫が必要  - accepted / - tried

setTimeout を使えば一定時間後に実行されるタスクを設置することができる。だけどそのタスクの本当の実行時間は精確ではない。(詳しくはEvent Loopを見てください。)。

ほとんどの場合はこれが問題にならないが、テストする時などではちょっと困る。

例えば、5. leading & trailingをサポートするthrottle() を実装する では精確なタイマーが必要になる。

Event Loopの問題なく、精確なsetTimeout()clearTimeout()を作ってくだい。これもFakeTimes がやっていることです。

「精確」というのは、関数の実行時間を0とし、時間は0からスタートすると、setTimeout(func1, 100)ではfunc1が必ず時間:100に実行される。

Date.now()の実装も入れ替える必要がある。

class FakeTimer {  install() {    // setTimeout(), clearTimeout(), and Date.now()     // are replaced  }  uninstall() {    // restore the original APIs    // setTimeout(), clearTimeout() and Date.now()  }  tick() {     // run all the schedule functions in order  }}

あなたのコードはこんな感じでテストされる。

const fakeTimer = new FakeTimer()fakeTimer.install()const logs = []const log = (arg) => {   logs.push([Date.now(), arg])}setTimeout(() => log('A'), 100)// log 'A' at 100const b = setTimeout(() => log('B'), 110)clearTimeout(b)// b is set but clearedsetTimeout(() => log('C'), 200)expect(logs).toEqual([[100, 'A'], [200, 'C']])fakeTimer.uninstall()

補足

時間に関係する関数の中ではDate.now()だけ対応が必要、その他は無視して良い。

常にもっといい方法を求めよう。