日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Node.js Promise.all 限制并发数量

發布時間:2025/3/19 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Node.js Promise.all 限制并发数量 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為什么80%的碼農都做不了架構師?>>> ??

Promise.all 本身不負責執行,執行過程在傳遞給Promise.all之前已經開始,Promise.all只等待全部執行完成,執行resolve,或碰到有執行失敗,立即執行reject部分。Promise.all非常好用,唯一的問題是,不能限制并發數量,所有任務同時開始執行,因為Promise.all本身不負責執行具體任務,所以也無法實現并發控制。

實現一個簡單的可以控制并發數量的Promise.allLimit函數,可以通過參數來控制并發數量。代碼:

/* promise-limit.js */ /* jshint esversion: 6 */ /*jslint node: true */ Promise.allLimit = function(arr, wrap, limit, callback) {return new Promise((resolve, reject) => {var total = arr.length;var result = new Array(total);var rejected = false;var dones = 0;function run(n) {setTimeout(() => {wrap(n, arr.shift()).then(res => {return typeof callback === 'function' ? callback(n, res) : Promise.resolve(res);}).then(res => {dones++;result[n] = res;if (!rejected) {if (arr.length) {run(total - arr.length);} else if (dones === total) {resolve(result);}}}).catch(err => {rejected = true;reject(err);});}, 0);}arr.slice(0, limit).forEach((v, n) => {run(n);});}); };

同樣返回一個Promise對象,可以直接替換Promise.all,不同的是,需要傳遞一個函數(wrap參數),用來包裹生成每一個具體執行的Promise對象,limit用來限定并發數量,在指定并發任務內,一個任務完成后,再吸入一個新任務繼續執行。

callback用來解析每一次任務完成后所需要的后續動作,比如存儲下載的內容、或將參數做變換,必須也返回一個Promise對象。

測試代碼:

Promise.allLimit([2000, 1500, 2500, 3000, 1500], function(n, time) {return new Promise((resolve, reject) => {console.log("Start Job: ", n, time);// setTimeout(2500 === time ? reject : resolve, time, "Time: " + time); // 測試rejectsetTimeout(resolve, time, "Time: " + time);}); }, 2, (n, res) => {// log Job n doneconsole.log("Done Job: ", res);return Promise.resolve(n); // log Job n done }).then(result => {console.log("All Done: ", result); }).catch(err => {console.log("Error: ", err); });

最后貢獻一個下載妹子圖的簡單代碼,默認控制并發數量10個。

#!/usr/bin/env node/* jshint esversion: 6 */ /*jslint node: true */ require('./promise-limit.js');const FS = require('fs'); const PATH = require('path'); const UTIL = require('util'); const ARGV = require('yargs').argv; const REQUEST = require('request'); const CHEERIO = require('cheerio');if (!ARGV.url || !ARGV.dir || !/\/$/.test(ARGV.dir) || !ARGV.img || !ARGV.total || !ARGV.from || !ARGV.to) {console.log("usage: --url http://example.com --dir ./imgs/ --img '.main-image img' --total '共(\d+)頁' --from '.php' --to '_%d.php' ");process.exit(); }const parallel = ARGV.parallel || 10; //并發數量const headers = {'Referer': ARGV.url,'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8','Accept-Encoding': 'gzip, deflate, sdch','Accept-Language': 'en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4','User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36' };function fetch(url, encoding = 'utf8') {return new Promise((resolve, reject) => {REQUEST({url: url,headers: headers,gzip: true,encoding: encoding}, (error, response, body) => {if (error) {reject(error);} else {resolve(body);}});}); }function write(file, content) {return new Promise(function(resolve, reject) {FS.writeFile(file, content, function(err) {if (err) {reject(err);} else {resolve();}});}); }fetch(ARGV.url).then(rsp => {const total = parseInt((rsp.match(new RegExp(ARGV.total)) || [0, 0])[1]);if (!total) {throw new Error('Match total error');}console.log("Total: %d, Parallel: %d", total, parallel);return Promise.allLimit(Array.from({length: total}, (v, k) => k + 1), (k, v) => {return fetch(v === 1 ? ARGV.url : ARGV.url.replace(ARGV.from, UTIL.format(ARGV.to, v)));}, parallel, (k, res) => {let src = CHEERIO.load(res)(ARGV.img).attr('src');let file = (k + 1) + PATH.extname(src);return fetch(src, null).then(img => {return write(ARGV.dir + file, img);}).then(() => {console.log("OK: [" + file + "]\t" + src);return file;}).catch(err => {console.log("ER: [" + file + "]\t" + src + " : " + err.toString());});});}).then(rsp => {console.log("All Jobs Done: ");console.log(rsp);}).catch(err => {console.log("Fetch failed: %s", err.toString());});

執行:

./request.js --total '(\d+)</span></a><a[^<>]+><span>下一頁' --from '/71636' --to '/71636/%d' --img '.main-image img' --dir ./71636/ --url 'http://www.mzitu.com/71636' --parallel 10

轉載于:https://my.oschina.net/jsk/blog/789877

總結

以上是生活随笔為你收集整理的Node.js Promise.all 限制并发数量的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。