async.mapLimit 并发请求限制的一点实践

每个项目产品都会让你加埋点,你是愿意花几天一个个加,还是愿意几分钟一个小时加完去喝茶聊天?来试试这520web工具, 高效加埋点,目前我们公司100号前端都在用,因为很好用,所以很自然普及开来了,推荐给大家吧 自己开发所以免费,埋点越多越能节约时间,点两下埋点就加上了,还不会犯错,里面有使用视频,反正免费 😄

上回参考《使用 eventproxy 控制并发》学习未能解决网站对并发请求进行限制的问题。这回继续学习《使用 async 控制并发》,目标是输出 CNode(https://cnodejs.org/ ) 社区首页的所有(40个)主题的标题,链接和第一条评论。

一个简单的callback实例 function add_callback(p1, p2 ,callback) { var my_number = p1 + p2; callback(my_number); } add_callback(5, 15, function(num){ console.log("call " + num); }); //call 20 add_callback函数的第三个参数是回调函数。当函数执行时,传递的结果作为callback的参数。

async.mapLimit async是一个流程控制工具包,提供了直接而强大的异步功能。基于Javascript为Node.js设计,同时也可以直接在浏览器中使用。

async异步流程控制模式包括,串行(series),并行(parallel),瀑布(waterfall)等。

async主要实现了三个部分的流程控制功能:

集合: Collections 流程控制: Control Flow 工具类: Utils 这次用到的是集合中的mapLimit(coll, limit, iteratee, callback opt) 每次以指定的最大limit数执行异步操作。参数如下:

名称 类型 描述 coll Array / Iterable / object 要迭代的集合。 limit number 一次异步操作的最大数量。 iteratee AsyncFunction 对于 coll 中的每一个item,迭代执行该异步函数。用(item, callback)调用,callback可选。 callback [ function ] 所有iteratee 函数完成后或发生错误时触发的回调函数。用(err, results)调用。results可以是iteratee 函数完成后触发callback时传递的项。 具体实现:

var superagent = require(superagent) var cheerio = require(cheerio) var async = require(async) var url = require(url)

var cnodeUrl = https://cnodejs.org/;

superagent.get(cnodeUrl).end(function(err, res) { if (err) { return console.error(err) } // 存放标题url的数组 var topicUrls = []; var $ = cheerio.load(res.text); //获取首页所有的链接 $(#topic_list .topic_title).each(function (idx, el) { if (idx < 40) { var $el = $(el); var href = url.resolve(cnodeUrl, $el.attr(href)); topicUrls.push(href); } }); //并发连接数的计数器 var concurrencyCount = 0; var fetch = function (url, callback) { console.time( 耗时); concurrencyCount++; superagent.get(url).end( function (err, res) { console.log(并发数:, concurrencyCount--, fetch, url); //var $ = cheerio.load(res.text); callback(null, [url, res.text]); });

} async.mapLimit(topicUrls, 11, function (topicUrl, callback) { fetch(topicUrl, callback); console.timeEnd(" 耗时"); }, function (err, result) { result = result.map( function (pair) { var $ = cheerio.load(pair[1]); return ({ title: $(.topic_full_title).text().trim(), href: pair[0], comment1: $(.reply_content).eq(0).text().trim(), author1: $(.reply_author).eq(0).text().trim() || "评论不存在", }); }); console.log(final: ,result); }); }); $ node app.js 耗时: 2.108ms 耗时: 0.748ms 耗时: 0.641ms 耗时: 0.596ms 耗时: 1.060ms 耗时: 1.429ms 耗时: 0.728ms 耗时: 0.653ms 耗时: 1.177ms 耗时: 0.820ms 耗时: 3.520ms 并发数: 11 fetch https://cnodejs.org/topic/5a54a8a4afa0a121784a8ab0 耗时: 0.802ms 并发数: 11 fetch https://cnodejs.org/topic/5a61ad4ece45d44045146172 耗时: 0.703ms 并发数: 11 fetch https://cnodejs.org/topic/5a66e5899288dc81532880b0 耗时: 0.694ms

经验分享 程序员 微信小程序 职场和发展