この解答例はChatGPTによって生成されています,正しいかは自己判断で。

BFE.devでのAI解答例 - JavaScript コーディング問題
101. 同一API callをマージする

解法

キャッシュの実装となると、どこにキャッシュを置くかが問題となってくる。

今回の問題では、createGetAPIWithMerging() 関数が返す関数 getAPIWithMerging() にキャッシュを実装することで解決する。

getAPIWithMerging() は受け取ったパスとコンフィグが前回のパスとコンフィグと同一かどうかをチェックする。

自分が書いたコードでは、ここで self を加えた配列にパスとコンフィグを格納している。これは、配列の includes() メソッドを使用して直接比較ができるようにするためである。一方で新しいデータをキャッシュに追加する度に Array.shift() で古いデータをずらすことで処理を高速化している。

同一である場合には、最後にキャッシュされた Promise インスタンスを返す。

それ以外の場合には、キャッシュを消すことを期待して Promise を新規に返し、処理が終わった際に次のキャッシュ用 Promise を保存する。

このとき、既にキャッシュに5つの Promise インスタンスが入っていれば、もっとも古いものをキャッシュから消して新しいものを追加する。余計なキャッシュを削除しないとメモリリークを起こす可能性があるため、この操作は重要である。

さらに、clearCache() メソッドを追加することで、キャッシュされた Promise インスタンスを削除できるようにする。これは、テストの実行時にキャッシュを削除して新しいテストコードを実行するために必要となる。

/**
 * @param {Function} getAPI
 * @returns
 */
function createGetAPIWithMerging(getAPI) {
  // キャッシュの初期化
  const cache = [];

  return function getAPIWithMerging(path, config) {
    const self = [path, config];

    const cacheIndex = cache.findIndex(item =>
      JSON.stringify([item[0], item[1]]) === JSON.stringify(self)
    );

    // キャッシュがある場合
    if (cacheIndex >= 0) {
      return cache[cacheIndex][2];
    }
    // キャッシュがない場合
    else {
      const promise = getAPI(path, config);

      cache.push([path, config, promise]);

      if (cache.length > 5) cache.shift();

      promise.then(() => {
        cacheIndex >= 0 && (cache[cacheIndex][2] = promise);
      });

      return promise;
    }
  };
}

// 追加機能:キャッシュを削除するclearCache()
createGetAPIWithMerging.clearCache = function() {
  this.cache.length = 0;
};