1.用 eventproxy 实现控制并发:

var EventProxy = require('eventproxy');

const most = 5;//并发数5
var urllist = [....];//待抓取url列表,100个 function foo(start){
var ep = new EventProxy();
ep.after('ok',most,function(){
foo(start+most);//一个批次任务完成,递归进行下一批任务
});
var q=0;
for(var i=start;i<urllist.length;i++){
if(q>=most){
break;//最多添加most个任务
}
http.get(urllist[i],function(res){
//....
res.on('end',function(){
ep.emit('ok');//一个任务完成,触发一次ok事件
});
});
q++;
}
}
foo(0);

2.使用 async.mapLimit 控制并发

var async = require('async');

//模拟一组连接地址
var urls = [];
for(var i = 0; i < 30; i++) {
urls.push('http://datasource_' + i);
}
console.log(urls); // 并发连接数的计数器
var concurrencyCount = 0; // 并发抓取数据的过程
var fetchUrl = function (url, callback) {
// delay 的值在 2000 以内,是个随机的整数
var delay = parseInt((Math.random() * 10000000) % 2000, 10);
concurrencyCount++;
console.log('现在的并发数是', concurrencyCount, ',正在抓取的是', url, ',耗时' + delay + '毫秒');
setTimeout(function () {
concurrencyCount--;
//抓取成功,调用回调函数
callback(null, url + ' html content');
}, delay);
}; //使用 async.mapLimit 来 5 个并发抓取,并获取结果
async.mapLimit(urls, 5, function (url, callback) {
fetchUrl(url, callback);
}, function (err, result) {
//所有连接抓取成功,返回回调结果列表
console.log('final:');
console.log(result);
});

3.async.queue 非常合适用来控制并发

/**
* Created by admin on 16/3/20.
*/
"use strict"
var http = require('http');
var cheerio = require('cheerio');
var URL = require('url');
var path = require('path');
var fs = require('fs');
var async = require('async'); var baseUrl = "http://cnodejs.org/";
var targetUrl = "http://cnodejs.org/";
var stime = new Date(); function sGet(url,callback){
var chunks = [];
http.get(url,(res)=>{
if (res.statusCode != '200') {
callback({message:"抓取失败,状态码:"+res.statusCode,url:url});
return;
}
res.on('data',(chunk)=>{
chunks.push(chunk);
});
res.on('end',()=>{
callback(null,Buffer.concat(chunks).toString());
});
}).on('error',(e)=>{
callback({message:"抓取失败",url:url,err:e});
});
} sGet(targetUrl,(err,data)=>{
if (err) {
console.log(err);
return false;
}
var $ = cheerio.load(data);
var anchors = $("#topic_list a.topic_title");
console.log('共'+anchors.length+'个任务'); const most=5;//并发数
//创建队列并指定并发数
var q=async.queue(function(url,callback){
var filename = path.basename(url)+'.txt';
sGet(url, (err, data)=> {
if (err) {
callback(err);
return false;
}
fs.writeFile('./html/' + filename, data, function (err) {
if (err) {
throw err;
}
callback(null,filename);
});
});
},most); q.drain = function() {
console.log('任务全部完成,共耗时:'+(new Date()-stime)+'ms');
} anchors.each(function(){
var url = URL.resolve(baseUrl,$(this).attr('href'));
q.push(url,function(err,filename){
if (err) {
console.log(err);
return;
}
console.log("finished:"+filename);
});
});
});

nodejs 并发控制的更多相关文章

  1. Nodejs爬虫进阶=>异步并发控制

    之前写了个现在看来很不完美的小爬虫,很多地方没有处理好,比如说在知乎点开一个问题的时候,它的所有回答并不是全部加载好了的,当你拉到回答的尾部时,点击加载更多,回答才会再加载一部分,所以说如果直接发送一 ...

  2. Nodejs爬虫进阶教程之异步并发控制

    Nodejs爬虫进阶教程之异步并发控制 之前写了个现在看来很不完美的小爬虫,很多地方没有处理好,比如说在知乎点开一个问题的时候,它的所有回答并不是全部加载好了的,当你拉到回答的尾部时,点击加载更多,回 ...

  3. 架构选型之Nodejs与Java

    前言: 身边越来越多的同事谈论Nodejs,谈其异步IO.事件回调.前后台统一一门语言,创业的朋友的第一个创业项目也选择了Nodejs,期望能够使用一种语言节省成本快速完成需求开发.与其他项目组的同事 ...

  4. java程序员的NodeJS初识篇

    摘要 作为一个一直用java来写后端的程序员用NodeJS来写后台,实在不是很爽.这里记下这两个月的NodeJS学习所遇之坑,与java转NodeJS的同仁共勉.学习时间不长,若有理解错误,望指正. ...

  5. nodejs 使用superagent+cheerio+eventproxy爬取豆瓣帖子

    //cnpm install superagent cheerio eventproxy fs pathvar superagent = require('superagent'); var chee ...

  6. nodejs爬虫案例笔记

    用nodeJs制作一个简单的网页爬虫 主要分为三个步骤,向目标请求数据,处理数据,打印数据.需要用到的模块有http,cheerio. 1.准备步骤,引入要使用的模块 2.向目标请求数据 http.g ...

  7. nodejs常用模块

    推荐的入门教程: <七天学会NodeJS>  https://github.com/nqdeng/7-days-nodejs <Node.js 包教不包会> https://g ...

  8. nodeJs + js 大文件分片上传

    简单的文件上传 一.准备文件上传的条件: 1.安装nodejs环境 2.安装vue环境 3.验证环境是否安装成功 二.实现上传步骤 1.前端部分使用 vue-cli 脚手架,搭建一个 demo 版本, ...

  9. NodeJs之OS

    OS Node.js提供了一些基本的底层操作系统的模块OS. API var os = require('os'); console.log('[arch] 操作系统CPU架构'+os.arch()) ...

随机推荐

  1. C# 判断是否是在设计模式下有效的方法

    public static bool IsDesignMode() { bool returnFlag = false; #if DEBUG if (LicenseManager.UsageMode ...

  2. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(11):XML和Annotation装配Bean的混合使用(@ImportResource)

    一.XML和Annotation装配Bean如何合理使用 引入第三方资源包中类的时候,建议使用XML配置,而使用自己编写的Java类的时候,推荐使用Annotation注解配置Bean. 二.关于注解 ...

  3. read与write

    函数原型 ssize_t read(int filedes, void *buf, size_t count);   ssize_t write(int filedes, void* buf, siz ...

  4. spring事务以及springweb

    什么是事务.事务特性.事务隔离级别.spring事务传播特性 https://www.cnblogs.com/zhangqian1031/p/6542037.html Spring AOP 中@Poi ...

  5. 通过python实现wc基本功能

    ---恢复内容开始--- 1.Github项目地址: https://github.com/zhg1998/ww/blob/master/wc.py 2.项目相关要求: 写一个命令行程序,模仿已有wc ...

  6. spring boot 整合 HttpClient

    第一步:引入HttpClient 的jar包 1.httpClient 5.0 开始支持异步(Async)请求: 2.httpclient 版本过低上传文件会出,原因是 org.apache.http ...

  7. jquery页面加载效果

    此为有时页面加载很慢时体验效果很不好而写的加载动画 CSS样式: #loading{position:%;left:%;width:124px;height:124px;overflow:hidden ...

  8. C#多线程编程实战1.1创建线程

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  9. BitArray简单例子

    using System; using System.Collections; using System.Text; namespace TestConsole { class Program { s ...

  10. ES6——let 和 const

    Let 1.使用 Let声明的变量,所声明的变量只在命令所在的代码块内有效. { Let a=1; var b=2; console.log(a) //在代码块里面 可以正常输出a } console ...