我实现的Node.js中类似Sleep的功能,请大家点评! - CNode技术社区

我实现的Node.js中类似Sleep的功能,请大家点评!
发布于 11 年前 作者 i2Worker 17785 次浏览 最后一次编辑是 9 年前 来自 分享

最近在抓取一个网站的数据,它有反爬虫策略,不让我持续访问超过100个网络链接,如果访问一段时间暂停一会的话就可以绕过去了,所以就有了下面这段代码,请大家看看,有没有更好的实现方法,首先说明一下,这个小程序运行在命令行下就可以了,我只要抓取数据就可以了。 实现的思路: 主要是通过setTimeout来实现暂停功能,将要抓取的连接保存在一个数组中,将数组进行分组,每抓取完3个连接就暂停5秒钟,并且结果统一保存在一个外部变量results中。

//测试Nodejs怎样实现Sleep的功能
var async = require('async');
//通过setTimeout函数实现Sleep的功能
var sleep = function(array, callback) {
 'use strict';
 //初始化变量
 var results = []; //存放最终结果
 var tmpArray = array.slice(0); //拷贝一份数据,防止改变变量外部的值
 var isEnd = false;
 //自调用函数
 var run = function() {
 var tmp = null; //存放截取的数组
 if (tmpArray.length > 3) {
 tmp = tmpArray.splice(0, 3);
 } else {
 tmp = tmpArray;
 isEnd = true;
 }
 async.mapLimit(tmp, 2, function(item, itemCallback) {
 console.log('Enter: ' + item.name);
 setTimeout(function() {
 console.log('Handle: ' + item.name);
 itemCallback(false, item.name + '!!!');
 }, item.delay);
 }, function(err, data) {
 console.log(data);
 results = results.concat(data);
 if (isEnd) {
 callback(false, results);
 } else {
 console.log('Sleep 5s');
 setTimeout(run, 5000);
 }
 });
 };
 run();
};
//测试数据
var arr = [
 {name:'Jack', delay:2000},
 {name:'Mike', delay: 1000},
 {name:'Freewind', delay:3000},
 {name:'Test', delay: 2500},
 {name:'Woody', delay: 3500},
 {name:'Water', delay: 2600},
 {name:'Sugar', delay: 1500}
];
sleep(arr, function(error, data) {
 'use strict';
 console.log(data);
});
9 回复

有 setTimeout 还非要去实现一个 sleep, 很强烈的 Java/C# 即视感.

@TossShinHwa 这个本来就是用的setTimeout功能,只是用它来实现暂停而已。

表示无法理解楼主心态

其实就是递归转迭代??

let arr = [
 {name:'Jack'},
 {name:'Mike'},
 {name:'Freewind'},
 {name:'Test'},
 {name:'Woody'},
 {name:'Water'},
 {name:'Sugar'}
]
function sleep(ms) {
 return new Promise(resolve => setTimeout(resolve, ms))
}
function download(name) {
 return new Promise(resolve => setTimeout(
 () => resolve('result for ' + name),
 Math.floor(Math.random() * 1000)
 ))
}
(async function main() {
 const concurrency = 3;
 for (let i = 0; i < arr.length; i+=concurrency) {
 console.log(i, '----')
 let task = [];
 for (let j = 0; j < concurrency && i +j < arr.length; j++) {
 task.push(download(arr[i+j].name));
 }
 var result = await Promise.all(task)
 console.log(result)
 await sleep(5000)
 }
})()

@qingfeng 好精巧的sleep函数。我在这里学习了。谢谢!!

就是用 settimeout 实现了自己的等待逻辑而已。没什么好点评的

var arr = [
 {name:'Jack', delay:2000},
 {name:'Mike', delay: 1000},
 {name:'Freewind', delay:3000},
 {name:'Test', delay: 2500},
 {name:'Woody', delay: 3500},
 {name:'Water', delay: 2600},
 {name:'Sugar', delay: 1500}
];
function sleep(array, callback) {
 function next() {
 var data = array.shift();
 if (data) {
 setTimeout(next, data.delay);
 callback(null, data.name);
 }
 }
 next();
}
sleep(arr, function (error, data) {
 console.log(data);
});

你这样写是递归,可以 setInterval 周期执行run不需要递归;递归的开销大 就是需要将请求的链接资源放在run外面, 和result一个作用域

另外run里面用的 var建议换成let 或者const 否则他们的作用域基本都和result差不多

回到顶部

AltStyle によって変換されたページ (->オリジナル) /