前端函数或请求的聚合

本文最后更新于:几秒前

场景

  • 某个请求被重复触发
  • 某个函数被重复触发

多次触发合并成一次,或一段时间内触发合并成一次。思路其实与节流类似

为什么?

  • 具体业务场景需要。如element-ui中上传组件多选文件会多次触发上传钩子,需要合并成一次上传
  • 性能优化考虑。某个高频的http请求进行聚合,降低请求频率

先举个例子,某个上传函数被多次触发

1
2
3
4
5
6
7
const upload = (filename) => {
console.log("正式上传", filename);
}

upload("a");
upload("b");
upload("c");

正式上传 a 正式上传 b 正式上传 c

需求: 希望多个文件能放在一次正式上传

宏任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const file = [];
const upload = (() => {
let collect = null;
return function(filename){
file.push(filename); // 记录要上传的文件
if(!collect){
collect = setTimeout(()=>{
console.log("正式上传", file);
collect = null;
},0);
}
}
})();

upload("a");
upload("b");
upload("c");

正式上传 [“a”, “b”, “c”]

思路:三次上传钩子实际上是同步代码,宏任务会在同步代码执行完成后再去触发。利用闭包记录下是否已经设置宏任务和需要上传的文件

微任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const file = [];
const upload = (() => {
let collect = null;
return function(filename){
file.push(filename);
if(!collect){
collect = Promise.resolve().then(()=>{
console.log("正式上传", file);
collect = null;
})
}
}
})();



upload("a");
upload("b");
upload("c");

正式上传 [“a”, “b”, “c”]

思路:其实跟宏任务一样,只不过promise.then会在同步代码后,setTimeout前触发

小结

总的来说,就是对原有的上传钩子进行了封装,或者叫代理。并利用事件循环的执行顺序,在合适的时机再去执行上传操作。

Q:那是不是只有以上两种方案呢?当然不是。思路一致,但是实现各有不同。

A:比如说,知道触发次数,可以考虑使用计数器在最后一次触发;标记变量可以使用其他写法来实现;

Q:我只想聚合一部分,怎么办?

A:setTimeout设置时间;或者设置临界值再推几个宏/微任务,注意记录文件做相应修改

Q:那异步触发的怎么去做聚合?

A:我可能是利用一下Promise.all吧。没有深入想,此处不多说。

说到聚合 + 性能优化,其实还有后端接口的聚合。利用中间层进行接口聚合,前端再去请求聚合后的接口,也能优化前端体验


前端函数或请求的聚合
https://www.chanx.tech/2021/37d4d9cb8c51/
作者
ischanx
发布于
2021年3月31日
更新于
2023年9月8日
许可协议