前段时间开发过程中遇到一个特殊的需求:
起初写了一个简单的爬虫, 用来爬取本地showdoc文档中所有的接口数据. 先随机访问一个页面, 拿到侧边栏的所有连接, 然后写一个循环, 使用node访问各个连接依次拿到所对应的数据
代码类似
Promise.all(urls.map(url => get(url))).then(resultArr => {
...
})
但是这时出现了一个问题, 因为接口数量比较多 (大概500个) 所以get方法一次发送了500个左右请求, 结果node会报错 socket hung up , 导致部分请求无法正常返回数据, 原因大概是请求太多 socket 被耗尽了(也可能是服务器的原因), 第一个想到的就是节流/去抖函数, 但是网上找了一圈, 发现没有合适我这个需求的, 我需要在短时间多次调用,
然后在之后的一段时间,把积累的调用次数慢慢的执行完, 一个都不能少!
没办法,只好自己写了一个. 在这里记录一下.
function delayCall(fn, delay) {
let arr = [] //用来储存每次调用传入的参数
//延迟调用函数
const _delayCall = function(context) {
setTimeout(() => {
//队列最前面的参数出队列
arr.shift()
//如果队列中还有未调用的参数, 则递归调用直到耗尽队列中的参数
if(arr.length > 0) {
fn.apply(context, arr[0])
_delayCall(context)
}
}, delay)
}
return function() {
const context = this
arr.push(arguments)
if(arr.length === 1) {
//第一次调用时立即调用
fn.apply(context, arguments)
_delayCall(context)
}
}
}
可以用一段代码测试
let i = 5
const delay = delayCall(function(e){ console.log(e) }, 500)
while(i--) delay(i)
这个函数可以实现密集调用, 缓慢执行的效果. 不介意的就收藏下,说不定以后用的着呢 ^_^