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

少し工夫が必要  - 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 100

const b = setTimeout(() => log('B'), 110)
clearTimeout(b)
// b is set but cleared

setTimeout(() => log('C'), 200)

expect(logs).toEqual([[100, 'A'], [200, 'C']])

fakeTimer.uninstall()

補足

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

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

(45)