环境
测试环境:electron + vue + axios
需求
想要做并行请求(比如爬虫)需要尽量快的请求页面。
假如一次发出请求到返回所需时间为100ms:
方案1(串行):请求一次接口等待返回处理结果后继续下一次请求。这样会受制于请求的速度,假如请求100次那么需要总时间为100ms * 100 = 10000ms
方案2(并行):利用Promise,同时发起多个请求,但不等待每个请求结束。而是Promise.all等待其全部结束再进行处理。假如请求100次那么需要总时间为100ms * 1= 100ms
可以看出速度有极大的提升,理论上(实际需要看机器配置和网络带宽情况)无论多少请求都只需要100ms。
并行实现
我们的需求就是方案2的并行实现。所以如下实现:
async t () { const time1 = new Date().getTime() / 1000 const task = [] for (let i=0; i < 100; i++){ task.push(this.t1()) // 发起请求 } await Promise.all(task) // 等待所有请求结束 // await this.$http.all(task) // 与Promise一样 const time2 = new Date().getTime() / 1000 console.log('time:', time2 - time1) }, async t1 () { const res = await this.$http({ method: 'get', baseURL: this.url, url: LOGIN_PATH, // 关键:正常url }) }
结果仍然是串行?
查看console程序的time输出很高,是所有请求时间累加的时间。
查看network,从time和waterfall也可以明显看出,
- 所有请求的开始时间点是一样的
- 但是后续请求都有等待时间(灰色),都是上一个请求开始到结束时间
- 每个请求的真正时间(绿色)几乎一样,但总时长越往后请求越慢,都是上一个请求结束才开始下一个
- 以上看出完全是串行请求,并没有达到我们的预期
network图如下:
问题在哪?
我们都知道浏览器中请求都应该是并行的,html中加载网络文件和请求也通常都是并行的。
观察发现这里所有经过url都是一致的,而一般网页开发时很少出现一个页面请求多次同样的url的,所以这里很可疑。
经过尝试,将每次url都改为不完全一样,确实解决了此问题。(怀疑是浏览器的问题,非axios问题。而之后使用node版的got未发现此问题)
修改代码,请求的url增加随机参数使其完整url每次都发生变化,修改部分代码如下:
async t1 () { const res = await this.$http({ method: 'get', baseURL: this.url, // url: LOGIN_PATH, // 关键:正常url url: LOGIN_PATH + `?v=${Math.random()}`, // 关键:增加随机参数 }) }
查看console的程序输出时间已经为几乎只有一个请求的时间。
查看network所有请求也都同时开始,也几乎(网络因素影响,不可能每次时间都一样)同时结束,总耗时只有200ms多
查询资料及测试发现,“chrome + jquery”并行请求看起来是6个一块,与资料所述chrome浏览器http最大连接数为6一致,基本可以判定这次主要问题在于浏览器或者electron(实际扔使用的chrome内核)连接数有关,还有些问题,比如如何修改连接数等这里不再深究。一些参考资料如下:
electron中使用got未发现此问题,这个库是node环境库,可能不经过chrome内核
来源:oschina
链接:https://my.oschina.net/watcher/blog/4408409