Skip to content

虚拟代理合并 HTTP 请求

假设我们在做一个文件同步的功能,当我们选中一个 checkbox 的时候,它对应的文件就会被同 步到另外一台备用服务器上面,

html
<body>
  <div id="proxy">
    <input type="checkbox" id="1" />1
    <input type="checkbox" id="2" />2
    <input type="checkbox" id="3" />3
    <input type="checkbox" id="4" />4
    <input type="checkbox" id="5" />5
    <input type="checkbox" id="6" />6
    <input type="checkbox" id="7" />7
  </div>
  <script>
    proxy.addEventListener('click', (e) => {
      const { target } = e
      if (target.checked) {
        synchronousFile(target.id)
      }
    })

    const synchronousFile = (id) => {
      // request...
      console.log(id)
    }
  </script>
</body>

当我们选中 3 个 checkbox 的时候,依次往服务器发送了 3 次同步文件的请求。而点击一个 checkbox 并不是很复杂的操作,我们可以在 1s 内点击多个,如此频繁的网络请求将会带来相当 大的开销。解决方案是,我们可以通过一个代理函数 proxySynchronousFile 来收集一段时间之 内的请求,最后一次性发送给服务器。比如我们等待 2 秒之后才把这 2 秒之内需要同步的文件 ID 打包发给服务器,如果不是对实时性要求非常高的系统,2 秒的延迟不会带来太大副作用,却 能大大减轻服务器的压力。

javascript
proxy.addEventListener('click', (e) => {
  const { target } = e
  
  if (target.checked) {
    proxySynchronousFile(target.id)
  }
})

const synchronousFile = (ids) => {
  // request...
  console.log(ids.slice())
}

const proxySynchronousFile = (function () {
  let ids = []
  let timer = null
  
  return function (id) {
    ids.push(id)

    if (!timer) {
      timer = setTimeout(() => {
        synchronousFile(ids)
        clearTimeout(timer)
        timer = null
        ids = []
      }, 2000)
    }
  }
})()