---
# System prepended metadata

title: 足立さんフロントエンド選考課題

---

# 足立さんフロントエンド選考課題

## 引数に受け取った関数の debounced 版を返す関数を実装してください

最後に実行されてから `wait` ms 経過するまで次の `func` の実行を遅延する、debounced 版の `func` を返却する関数を実装してください。


返却値である debounced 版の関数は `wait` ms 後の `func` の実行をキャンセルする `cancel` メソッドと、実行されたらすぐ `func` を実行してその結果を返す `flush` メソッドを提供するものとします。
`func` は debounced 版の関数が最後に受け取った引数と共に実行されます。また debounced 版の関数は最後の `func` の実行結果を戻値とします。

以下は上述の仕様を確認するための使用例です (`//=>` はコンソールの出力を示しています):

```ts
// ユーティリティ関数です
const sleep = (d: number) => new Promise(resolve => setTimeout(resolve, d))
const log = (...args: any) => console.log(`[${new Date().toUTCString()}] `, ...args)

// debounce 対象の関数
function inc(x: number) {
  log(`inc called with ${x}.`)
  return x + 1
}

;(async () => {
  // inc の実行を 1s 遅延する debounced 版の関数を得る
  const debounced1s = debounce(inc, 1000)
  log(debounced1s(100)) //=> undefined
  // 1 s 後にコンソールに「inc called with 100.」と出力される
  await sleep(5000)

  log(debounced1s(300)) //=> 101、直近の実行結果を返す
  await sleep(100)
  log(debounced1s(300)) //=> 101
  await sleep(100)
  log(debounced1s(300)) //=> 101
  // 1 s 後にコンソールに「inc called with 300.」と出力される
  await sleep(5000)

  log(debounced1s(300)) //=> 301
  // 1 s 後にコンソールに「inc called with 300.」と出力される
  await sleep(5000)

  // inc の実行を 2s 遅延する debounced 版の関数を得る
  const debounce2s = debounce(inc, 2000)
  log(debounce2s(100)) //=> undefined
  debounce2s.cancel()
  // 2 s 後にコンソールに何も出力されない
  await sleep(5000)

  // inc の実行を 10s 遅延する debounced 版の関数を得る
  const debounce10s = debounce(inc, 10000)
  log(debounce10s(100)) //=> undefined
  log(debounce10s.flush()) //=> 101
  // このタイミングでコンソールに「inc called with 100.」と出力される
})()
```

より現実的な例としては、Ajax リクエストが絡むフォームの自動補完機能での利用が考えられます。
例えば Twitter の検索フォームのように、ユーザの入力文字列に部分一致するアイテムを Ajax リクエストでサーバに問い合わせ、その結果を表示してユーザが選べるようにする機能を実装することを考えます。
このとき `keypress` イベントが発火する度に Ajax リクエストを送る実装だとサーバに無駄な負荷がかかってしまいます。
サーバへのリクエストを行う関数の debounced 版を用意すれば、例えば最後の `keypress` イベントから 50ms 経過するまでは何度イベントが発火されてもリクエストを送らないようにすることができます。

## 実装

```js
# 実際に動くかどうかよりも、コミュニケーションを取りながら作業を進められるかどうかをみています。
# もし詳細APIが分からなければ、「こういう関数があると想定して」で進めて頂いて大丈夫です。


const debounce = (func, d) => {
  const anyFunc = (args) => {
    let result;
    setTimeout(() => {
      result = func(args);
    }, d);
    return result;
  };
  return anyFunc;
};  

```