时间窗口

在一定时间内,如果请求同一个 url,则只请求一次。

const fetch = require("node-fetch");

function hash(...args) {
  return args.join(",");
}

function window_request(f, time = 50) {
  let w = {};
  // 是否有时间窗口
  let flag = false;

  return (...args) => {
    return new Promise((resolve) => {
      // 如果w中没有这次请求(通过hash存入), 如果有,则在最后 L54 将resolve存入到对应的resolvers里
      if (!w[hash(args)]) {
        w[hash(args)] = {
          func: f,
          args,
          // 将不同的request的resolve也添加进来,方便最后统一做处理。
          resolvers: [],
        };
      }

      // 如果没有时间窗口
      if (!flag) {
        // 接下来是创建一个时间窗口
        console.log("create a window");
        flag = true;
        setTimeout(() => {
          // 对w中每一个请求进行处理。
          Object.keys(w).forEach((key) => {
            // 获取参数进行执行
            const { func, args, resolvers } = w[key];
            console.log("run once ---- ", resolvers.length);
            func(...args)
              .then((res) => {
                return res.text();
              })
              .then((t) => {
                // 将获取到的结果批量放到resolve中处理
                resolvers.forEach((r) => {
                  console.log("result anywhere");
                  r(t);
                });
                // 重置访问窗口
                flag = false;
                w = {};
              });
          });
        }, time);
      }

      w[hash(args)].resolvers.push(resolve);
    });
  };
}

const request = window_request(fetch, 20);

request("https://www.baidu.com");
request("https://www.baidu.com");
request("https://www.baidu.com");
request("https://www.baidu.com");
request("https://www.baidu.com");
request("https://www.baidu.com");
request("https://www.baidu.com");
console.log("break");
setTimeout(() => {
  request("https://www.baidu.com");
  request("https://www.baidu.com");
  request("https://www.baidu.com");
  request("https://www.baidu.com");
  request("https://www.baidu.com");
  request("https://www.baidu.com");
  request("https://www.baidu.com");
}, 10000);