国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

15 行代碼實現并發控制(javascript)

gyl_coder / 3555人閱讀

摘要:而爬蟲一般用多線程來控制并發,然而如果是爬蟲,由于其單線程無阻塞性質以及事件循環機制,一般不用多線程來控制并發當然也可以實現多線程,此處非重點不再多講,而是更加簡便地直接在代碼層級上實現并發。下面我們用行代碼實現一個并發控制的函數。

前言

首發于 github blog

做過爬蟲的都知道,要控制爬蟲的請求并發量,其實也就是控制其爬取頻率,以免被封IP,還有的就是以此來控制爬蟲應用運行內存,否則一下子處理N個請求,內存分分鐘會爆。

python爬蟲一般用多線程來控制并發,

然而如果是node.js爬蟲,由于其單線程無阻塞性質以及事件循環機制,一般不用多線程來控制并發(當然node.js也可以實現多線程,此處非重點不再多講),而是更加簡便地直接在代碼層級上實現并發。

為圖方便,開發者在開發node爬蟲一般會找一個并發控制的npm包,然而第三方的模塊有時候也并不能完全滿足我們的特殊需求,這時候我們可能就需要一個自己定制版的并發控制函數。

下面我們用15行代碼實現一個并發控制的函數。

具體實現 參數

首先,一個基本的并發控制函數,基本要有以下3個參數:

list {Array} - 要迭代的數組

limit {number} - 控制的并發數量

asyncHandle {function} - 對list的每一個項的處理函數

設計

以下以爬蟲為實例進行講解

設計思路其實很簡單,假如并發量控制是 5

首先,瞬發 5 個異步請求,我們就得到了并發的 5 個異步請求

// limit = 5
while(limit--) {
    handleFunction(list)
}

然后,這 5 個異步請求中無論哪一個先執行完,都會繼續執行下一個list

let recursion = (arr) => {
    return asyncHandle(arr.shift())
        .then(()=>{
            // 迭代數組長度不為0, 遞歸執行自身
            if (arr.length!==0) return recursion(arr) 
            // 迭代數組長度為0,結束 
            else return "finish";
        })
}

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)
})

結果如下:




手動拋出異常中斷并發函數測試:

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 手動拋出異常,停止后續迭代:

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107238.html

相關文章

  • 《Node.js設計模式》基于回調的異步控制

    摘要:編寫異步代碼可能是一種不同的體驗,尤其是對異步控制流而言。回調函數的準則在編寫異步代碼時,要記住的第一個規則是在定義回調時不要濫用閉包。為回調創建命名函數,避免使用閉包,并將中間結果作為參數傳遞。 本系列文章為《Node.js Design Patterns Second Edition》的原文翻譯和讀書筆記,在GitHub連載更新,同步翻譯版鏈接。 歡迎關注我的專欄,之后的博文將在專...

    Chiclaim 評論0 收藏0
  • 一文詳解MySQL的鎖機制

    摘要:表級鎖表級鎖表級別的鎖定是各存儲引擎中最大顆粒度的鎖定機制。當前沒有其他事務持有表中任意一行的排他鎖。為了檢測是否滿足第二個條件,事務必須在確保表不存在任何排他鎖的前提下,去檢測表中的每一行是否存在排他鎖。一、表級鎖、行級鎖、頁級鎖數據庫鎖定機制簡單來說,就是數據庫為了保證數據的一致性,而使各種共享資源在被并發訪問變得有序所設計的一種規則。MySQL數據庫由于其自身架構的特點,存在多種數據存...

    番茄西紅柿 評論0 收藏2637
  • 【全文】狼叔:如何正確的學習Node.js

    摘要:感謝大神的免費的計算機編程類中文書籍收錄并推薦地址,以后在倉庫里更新地址,聲音版全文狼叔如何正確的學習簡介現在,越來越多的科技公司和開發者開始使用開發各種應用。 說明 2017-12-14 我發了一篇文章《沒用過Node.js,就別瞎逼逼》是因為有人在知乎上黑Node.js。那篇文章的反響還是相當不錯的,甚至連著名的hax賀老都很認同,下班時讀那篇文章,竟然坐車的還坐過站了。大家可以很...

    Edison 評論0 收藏0
  • 【全文】狼叔:如何正確的學習Node.js

    摘要:感謝大神的免費的計算機編程類中文書籍收錄并推薦地址,以后在倉庫里更新地址,聲音版全文狼叔如何正確的學習簡介現在,越來越多的科技公司和開發者開始使用開發各種應用。 說明 2017-12-14 我發了一篇文章《沒用過Node.js,就別瞎逼逼》是因為有人在知乎上黑Node.js。那篇文章的反響還是相當不錯的,甚至連著名的hax賀老都很認同,下班時讀那篇文章,竟然坐車的還坐過站了。大家可以很...

    fengxiuping 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<