介绍
大家好,我是大胆的番茄。
请求池是前端面试当中经常会问的一道题目:如何保证同时只有 N 个请求在发送,成功一个就再请求一个?
首先我们要理解为啥要设计一个请求池?主要还是从性能和浏览器并发来考量。浏览器设计当初就定义了浏览器打开页面,同时发送 http 请求的瞬时数量:
浏览器 |
HTTP 1.1 |
HTTP 1.0 |
Chrome |
6 |
6 |
Firefox |
6 |
6 |
Safari |
4 |
4 |
从上表可以看出,Chrome 最大可以同时发送 6 个请求,超过之后会有明显的等待时间。
所以我们从面试题开始看如何实现请求池,设计一个请求池,让下面的代码可以正常运行:
1 2 3 4 5 6 7 8 9 10 11 12 13
| const fetchPool = new FetchPool({ max: 3, });
for (let i = 0; i < 10; i++) { fetchPool('https://uquuu.com/yesorno') .then((value) => { console.log('value :>> ', i, value); }) .catch((error) => { console.log('error :>> ', i, error); }); }
|
废话不多说,上代码。
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| class FetchPool { options = { max: 6, }; queues = []; count = 0;
constructor(options) { this.options = { ...this.options, ...options };
return (input, init) => { return new Promise((resolve, reject) => { this.queues.push({ input, init, resolve, reject, }); this.runQueues(); }) } }
runQueues() { if (this.queues.length === 0) return; if (this.count >= this.options.max) return;
this.count++; const queue = this.queues.shift(); fetch(queue.input, queue.init).then((res) => { this.count--; this.runQueues(); return queue.resolve(res); }).catch((err) => { this.count--; this.runQueues(); return queue.reject(err); }) } }
|