node 使用 async 控制并发的方法


Posted in Javascript onMay 07, 2018

目标

建立一个 lesson5 项目,在其中编写代码。

代码的入口是 app.js,当调用 node app.js 时,它会输出 CNode(https://cnodejs.org/ ) 社区首页的所有主题的标题,链接和第一条评论,以 json 的格式。

注意:与上节课不同,并发连接数需要控制在 5 个。

输出示例:

[
 {
  "title": "【公告】发招聘帖的同学留意一下这里",
  "href": "http://cnodejs.org/topic/541ed2d05e28155f24676a12",
  "comment1": "呵呵呵呵"
 },
 {
  "title": "发布一款 Sublime Text 下的 JavaScript 语法高亮插件",
  "href": "http://cnodejs.org/topic/54207e2efffeb6de3d61f68f",
  "comment1": "沙发!"
 }
]

知识点

学习 async(https://github.com/caolan/async ) 的使用。这里有个详细的 async demo 演示:https://github.com/alsotang/async_demo

学习使用 async 来控制并发连接数。

课程内容

lesson4 的代码其实是不完美的。为什么这么说,是因为在 lesson4 中,我们一次性发了 40 个并发请求出去,要知道,除去 CNode 的话,别的网站有可能会因为你发出的并发连接数太多而当你是在恶意请求,把你的 IP 封掉。

我们在写爬虫的时候,如果有 1000 个链接要去爬,那么不可能同时发出 1000 个并发链接出去对不对?我们需要控制一下并发的数量,比如并发 10 个就好,然后慢慢抓完这 1000 个链接。

用 async 来做这件事很简单。

这次我们要介绍的是 async 的 mapLimit(arr, limit, iterator, callback) 接口。另外,还有个常用的控制并发连接数的接口是 queue(worker, concurrency),大家可以去 https://github.com/caolan/async#queueworker-concurrency 看看说明。

这回我就不带大家爬网站了,我们来专注知识点:并发连接数控制。

对了,还有个问题是,什么时候用 eventproxy,什么时候使用 async 呢?它们不都是用来做异步流程控制的吗?

我的答案是:

当你需要去多个源(一般是小于 10 个)汇总数据的时候,用 eventproxy 方便;当你需要用到队列,需要控制并发数,或者你喜欢函数式编程思维时,使用 async。大部分场景是前者,所以我个人大部分时间是用 eventproxy 的。

正题开始。

首先,我们伪造一个 fetchUrl(url, callback) 函数,这个函数的作用就是,当你通过

fetchUrl('http://www.baidu.com', function (err, content) {
 // do something with `content`
});

调用它时,它会返回 http://www.baidu.com 的页面内容回来。

当然,我们这里的返回内容是假的,返回延时是随机的。并且在它被调用时,会告诉你它现在一共被多少个地方并发调用着。

// 并发连接数的计数器
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);
};

我们接着来伪造一组链接

var urls = [];
for(var i = 0; i < 30; i++) {
 urls.push('http://datasource_' + i);
}

这组链接的长这样:

node 使用 async 控制并发的方法

接着,我们使用 async.mapLimit 来并发抓取,并获取结果。

async.mapLimit(urls, 5, function (url, callback) {
 fetchUrl(url, callback);
}, function (err, result) {
 console.log('final:');
 console.log(result);
});

运行输出是这样的:

node 使用 async 控制并发的方法

可以看到,一开始,并发链接数是从 1 开始增长的,增长到 5 时,就不再增加。当其中有任务完成时,再继续抓取。并发连接数始终控制在 5 个。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
传智播客学习之JavaScript基础篇
Nov 13 Javascript
js三种排序算法分享
Aug 16 Javascript
jQuery中get和post方法传值测试及注意事项
Aug 08 Javascript
HTML5使用DeviceOrientation实现摇一摇功能
Jun 05 Javascript
js+html5实现canvas绘制简单矩形的方法
Jun 05 Javascript
原生js与jQuery实现简单的tab切换特效对比
Jul 30 Javascript
再谈Javascript中的异步以及如何异步
Aug 19 Javascript
JavaScript实现前端实时搜索功能
Mar 26 Javascript
一个可复用的vue分页组件
May 15 Javascript
Vue.js学习笔记之修饰符详解
Jul 25 Javascript
Electron 调用命令行(cmd)
Sep 23 Javascript
Vue触发input选取文件点击事件操作
Aug 07 Javascript
Angular 数据请求的实现方法
May 07 #Javascript
JavaScript数组去重算法实例小结
May 07 #Javascript
JavaScript求一组数的最小公倍数和最大公约数常用算法详解【面向对象,回归迭代和循环】
May 07 #Javascript
详解VUE-地区选择器(V-Distpicker)组件使用心得
May 07 #Javascript
JavaScript实现的DOM树遍历方法详解【二叉DOM树、多叉DOM树】
May 07 #Javascript
Vue 实现树形视图数据功能
May 07 #Javascript
JavaScript 跨域之POST实现方法
May 07 #Javascript
You might like
PHP中的reflection反射机制测试例子
2014/08/05 PHP
PHP匿名函数(闭包函数)详解
2019/03/22 PHP
javascript编码的几个方法详细介绍
2013/01/06 Javascript
网站繁简切换的JS遇到页面卡死的解决方法
2014/03/12 Javascript
jquery 获取 outerHtml 包含当前节点本身的代码
2014/10/30 Javascript
JS+CSS实现自动改变切换方向图片幻灯切换效果的方法
2015/03/02 Javascript
jQuery原型属性和原型方法详解
2015/07/07 Javascript
不想让浏览器运行javascript脚本的方法
2015/11/20 Javascript
基于bootstrap插件实现autocomplete自动完成表单
2016/05/07 Javascript
JS操作xml对象转换为Json对象示例
2017/03/25 Javascript
Vue中如何实现轮播图的示例代码
2017/07/27 Javascript
Vue父组件调用子组件事件方法
2018/02/23 Javascript
Nuxt.js 数据双向绑定的实现
2019/02/17 Javascript
elementUI select组件默认选中效果实现的方法
2019/03/25 Javascript
Vue中computed、methods与watch的区别总结
2019/04/10 Javascript
详解如何给React-Router添加路由页面切换时的过渡动画
2019/04/25 Javascript
解决vue单页面应用中动态修改title问题
2019/06/09 Javascript
vue实现绑定事件的方法实例代码详解
2019/06/20 Javascript
Vue中img的src是动态渲染时不显示的解决
2019/11/14 Javascript
[01:27]2014DOTA2展望TI 剑指西雅图IG战队专访
2014/06/30 DOTA
[01:37]PWL S2开团时刻DAY1&2——这符有毒
2020/11/20 DOTA
python中for语句简单遍历数据的方法
2015/05/07 Python
详解Pytorch 使用Pytorch拟合多项式(多项式回归)
2018/05/24 Python
pandas值替换方法
2018/07/10 Python
Python实现的微信支付方式总结【三种方式】
2019/04/13 Python
Python高级特性——详解多维数组切片(Slice)
2019/11/26 Python
python可视化text()函数使用详解
2020/02/11 Python
Django Xadmin多对多字段过滤实例
2020/04/07 Python
python excel多行合并的方法
2020/12/09 Python
python palywright库基本使用
2021/01/21 Python
为什么UNION ALL比UNION快
2016/03/17 面试题
婚礼答谢词范文
2015/09/29 职场文书
详解nginx.conf 中 root 目录设置问题
2021/04/01 Servers
Oracle设置DB、监听和EM开机启动的方法
2021/04/25 Oracle
windows server2016安装oracle 11g的图文教程
2022/07/15 Servers
Java中的Kafka为什么性能这么快及4大核心详析
2022/09/23 Java/Android