15 行代码完成并发掌握(javascript)

媒介

首发于 github blog

做过爬虫的都晓得,要掌握爬虫的要求并发量,实在也就是掌握其爬取频次,以避免被封IP,另有的就是以此来掌握爬虫运用运转内存,不然一会儿处置惩罚N个要求,内存分分钟会爆。

python爬虫平常用多线程来掌握并发,

但是如果是node.js爬虫,因为其单线程无壅塞性子以及事宜轮回机制,平常不必多线程来掌握并发(固然node.js也能够完成多线程,此处非重点不再多讲),而是越发轻便地直接在代码层级上完成并发。

为图轻易,开辟者在开辟node爬虫平常会找一个并发掌握的npm包,但是第三方的模块有时候也并不能完整满足我们的特别需求,这时候我们能够就需要一个本身定制版的并发掌握函数。

下面我们用15行代码完成一个并发掌握的函数。

详细完成

参数

起首,一个基础的并发掌握函数,基础要有以下3个参数:

  • list {Array} – 要迭代的数组
  • limit {number} – 掌握的并发数目
  • asyncHandle {function} – 对list的每个项的处置惩罚函数

设想

以下以爬虫为实例举行解说

设想思绪实在很简单,如果并发量掌握是 5

  1. 起首,瞬发 5 个异步要求,我们就得到了并发的 5 个异步要求

    // limit = 5
    while(limit--) {
        handleFunction(list)
    }
  2. 然后,这 5 个异步要求中不管哪个先实行完,都邑继承实行下一个list

    let recursion = (arr) => {
        return asyncHandle(arr.shift())
            .then(()=>{
                // 迭代数组长度不为0, 递归实行本身
                if (arr.length!==0) return recursion(arr) 
                // 迭代数组长度为0,完毕 
                else return 'finish';
            })
    }
  3. list一切的项迭代完以后的回调

    return Promise.all(allHandle)

代码

上述步骤组合起来,就是

/**
 * @params list {Array} - 要迭代的数组
 * @params limit {Number} - 并发数目掌握数
 * @params asyncHandle {Function} - 对`list`的每个项的处置惩罚函数,参数为当前处置惩罚项,必需 return 一个Promise来肯定是不是继承举行迭代
 * @return {Promise} - 返回一个 Promise 值来确认一切数据是不是迭代完成
 */
let mapLimit = (list, limit, asyncHandle) => {
    let recursion = (arr) => {
        return asyncHandle(arr.shift())
            .then(()=>{
                if (arr.length!==0) return recursion(arr)   // 数组还未迭代完,递归继承举行迭代
                else return 'finish';
            })
    };
    
    let listCopy = [].concat(list);
    let asyncList = []; // 正在举行的一切并发异步操纵
    while(limit--) {
        asyncList.push( recursion(listCopy) ); 
    }
    return Promise.all(asyncList);  // 一切并发异步操纵都完成后,本次并发掌握迭代完成
}

测试demo

模仿一下异步的并发状况

var dataLists = [1,2,3,4,5,6,7,8,9,11,100,123];
var count = 0;
mapLimit(dataLists, 3, (curItem)=>{
    return new Promise(resolve => {
        count++
        setTimeout(()=>{
            console.log(curItem, '当前并发量:', count--)
            resolve();
        }, Math.random() * 5000)  
    });
}).then(response => {
    console.log('finish', response)
})

效果以下:

《15 行代码完成并发掌握(javascript)》

手动抛出非常中断并发函数测试:

var dataLists = [1,2,3,4,5,6,7,8,9,11,100,123];
var count = 0;
mapLimit(dataLists, 3, (curItem)=>{
    return new Promise((resolve, reject) => {
        count++
        setTimeout(()=>{
            console.log(curItem, '当前并发量:', count--)
            if(curItem > 4) reject('error happen')
            resolve();
        }, Math.random() * 5000)  
    });
}).then(response => {
    console.log('finish', response)
})

并发掌握状况下,迭代到5,6,7 手动抛出非常,住手后续迭代:
《15 行代码完成并发掌握(javascript)》

    原文作者:微雨微语
    原文地址: https://segmentfault.com/a/1190000013128649
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞