async
和eventproxy
同样都是控制并发的,eventproxy
会同时发起所有请求,所以在上一篇博客中最后出现了503
的错误;使用async
则可以很好地解决这个问题,使用async
能够控制并发线程的数量
一、async
- async在github : https://github.com/caolan/async
- async使用示例 : https://github.com/alsotang/async_demo
- async常用的方法有好几个,这里使用新增加的
mapLimit(collection,iteratee(item,callback),callback(err,results))
方法解决遗留的问题
二、使用async限制并发访问数量
1. demo
首先来个预热程序看看如何使用mapList方法:
var async=require("async");
var currentCount=0;
console.log("will create a url list size 10 !");
var urls=[];
for(var i=0;i<10;i++){
urls.push('http://www.example.com/'+i+".html");
}
async.mapLimit(urls,2,function(url,callback){
var delay=parseInt(500);
currentCount++;
console.log("currentCount is :"+currentCount+",current url is :"+url+",use time is :"+delay+" mm");
setTimeout(function(){
currentCount--;
callback(null,url+' html content ');
},delay);
},function(err,result){
console.log("result:");
console.log(result);
});
运行结果:
will create a url list size 10 !
currentCount is :1,current url is :http://www.example.com/0.html,use time is :500 mm
currentCount is :2,current url is :http://www.example.com/1.html,use time is :500 mm
currentCount is :2,current url is :http://www.example.com/2.html,use time is :500 mm
currentCount is :2,current url is :http://www.example.com/3.html,use time is :500 mm
currentCount is :2,current url is :http://www.example.com/4.html,use time is :500 mm
currentCount is :2,current url is :http://www.example.com/5.html,use time is :500 mm
currentCount is :2,current url is :http://www.example.com/6.html,use time is :500 mm
currentCount is :2,current url is :http://www.example.com/7.html,use time is :500 mm
currentCount is :2,current url is :http://www.example.com/8.html,use time is :500 mm
currentCount is :2,current url is :http://www.example.com/9.html,use time is :500 mm
result:
[ 'http://www.example.com/0.html html content ',
'http://www.example.com/1.html html content ',
'http://www.example.com/2.html html content ',
'http://www.example.com/3.html html content ',
'http://www.example.com/4.html html content ',
'http://www.example.com/5.html html content ',
'http://www.example.com/6.html html content ',
'http://www.example.com/7.html html content ',
'http://www.example.com/8.html html content ',
'http://www.example.com/9.html html content ' ]
2.mapLimit方法参数的含义说明
mapLimit方法的完整定义:
mapLimit(collection,iteratee(item,callback),callback(err,results))
collection : 一个数组
item : collection的一个元素
callback : 回调函数,该回调函数比较特殊,理解起来也比较困难,在iteratee方法中一定要调用该回调函数,一般来说会有三种常用的使用方法:
使用方法形式 | 意义 |
---|---|
callback(null) | 调用成功 |
callback(null,data) | 调用成功,并且返回数据data追加到results |
callback(data) | 调用失败,不会再继续循环,直接到最后的callback |
3.使用async限制并发访问数量完整代码
var express=require("express");
var superagent=require("superagent");
var cheerio=require("cheerio");
var url=require("url");
var eventproxy=require("eventproxy");
var async=require("async");
var app=express();
var baseUrl='https://cnodejs.org/';
function output(arr){
for(var i=0;i<arr.length;i++){
console.log(arr[i]);
}
}
superagent.get(baseUrl).end(function(err,resp){
if(err){
return console.error(err);
}
var arr=[];
var $=cheerio.load(resp.text);
$("#topic_list .topic_title").each(function(idx,element){
$element=$(element);
var _url=url.resolve(baseUrl,$element.attr("href"));
arr.push(_url);
});
//验证得到的所有文章链接集合
output(arr);
//接下来遍历arr,解析每一个页面中需要的信息
async.mapLimit(arr,3,function(url,callback){
superagent.get(url).end(function(err,mes){
if(err){
console.log("get \""+url+"\" error !"+err);
console.log("message info:"+JSON.stringify(mes));
}
console.log('fetch '+url+" succeful !");
//console.log("mess info:"+JSON.stringify(mes));
var $=cheerio.load(mes.text);
var jsonData={
title:$(".topic_full_title").text().trim(),
href:url,
firstcomment:$("#reply1 .markdown-text").text().trim()
};
console.log("aim data is :"+JSON.stringify(jsonData));
callback(null,jsonData);
});
},function(error,results){
console.log("result :");
console.log(results);
});
});
这样上一篇博客中的503错误就解决了。
网友评论