javascript - async/await:分批解析 Promise.all() N
问题描述
tl; dr 在 Promises 方面需要一些帮助。
这是所有核心的一个小刮板功能:
function request(method, url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = resolve;
xhr.onerror = reject;
xhr.send();
});
}
我还有一个相当大的配置文件列表,我想解决:
const profiles = ['http://www.somesite.com/profile/1',
'http://www.somesite.com/profile/2'] // 100+ more
我如何分批处理它们,比如一次 5 个?
到目前为止,这是我的思考过程:
- 使用_.chunk()分成 N 块
- 等待 Promise.all() 解析所述块
这是我到目前为止所拥有的:
async function processProfileBatch(batchOfUrls) {
let promises = [];
// Populate promises
for (let i = 0; i < batchOfUrls.length; i++) {
let url = batchOfUrls[i]
promises.push(request('GET', url))
}
// Wait for .all to resolve
return await Promise.all(promises)
}
const profileBatches = _.chunk(profileLinks, 3)
for (let i = 0; i < profileBatches.length; i++) {
let processedBatch = await processProfileBatch(profileBatches[i])
console.log(new Date(), 'processedBatch', processedBatch);
}
不幸的是,这只是返回ProgressEvent
s; 经过检查,其中包含的 xhr 已.responseText
设置为“”,即使readyState
是 4:
解决方案
分块的问题是您有 x 个活动请求,然后等待所有请求完成以开始下一个 x 数量的请求。
使用节流阀,您可以连续激活 x 数量的请求,直到所有请求都完成。
//lib comes from: https://github.com/amsterdamharu/lib/blob/master/src/index.js
const lib = require("lib");
function processProfileBatch(batchOfUrls){
const max10 = lib.throttle(10)
return Promise.all(
batchOfUrls.map(
url=>
max10(url=>request('GET', url))(url)
)
)
};
如果您希望限制每个周期的连接数(例如每秒 2 个)而不是限制活动连接数,您可以使用 throttlePeriod:
twoPerSecond = lib.throttlePeriod(2,1000);
... other code
twoPerSecond(url=>request('GET', url))(url)
当一个拒绝时,您可能还不想丢弃所有已解决的请求。对被拒绝的请求使用特殊的解析值,您可以将被拒绝的请求与已解决的请求分开:
//lib comes from: https://github.com/amsterdamharu/lib/blob/master/src/index.js
const lib = require("lib");
function processProfileBatch(batchOfUrls){
const max10 = lib.throttle(10)
return Promise.all(
batchOfUrls.map(
url=>
max10(url=>request('GET', url))(url)
.catch(err=>new lib.Fail([err,url]))
)
)
};
processProfileBatch(urls)
.then(//this does not reject because rejects are caught and return Fail object
result=>{
const successes = results.filter(lib.isNotFail);
const failed = results.filter(lib.isFail);
}
)
推荐阅读
- node.js - 有没有办法反向代理随机子域
- react-native - 如何在具有本机反应的 ScrollView 中自动滚动?
- amazon-web-services - 如何更新/重命名 SQS 队列名称
- angular - HttpClient 中的 jsonp 方法没有返回错误状态 0 而不是正确的状态
- matlab - 如何在Matlab中查找句柄图形对象的所有属性、方法、事件?
- jquery - Django:尝试实现文件上传进度条
- macos - Adobe Fonts(又名 Typkekit 又名 Creative Cloud Fonts)是否在我的 Mac 上存储字体?
- r - 在R中按字母顺序对每行字符串进行排序
- javascript - 引导切换开关在页面加载时显示错误的内容
- html - 调整屏幕大小时不显示导航栏链接