mym*_*and 5 javascript node.js promise bluebird
我有5亿个对象,其中每个都有n个联系人,如下所示
var groupsArray = [
{'G1': ['C1','C2','C3'....]},
{'G2': ['D1','D2','D3'....]}
...
{'G2000': ['D2001','D2002','D2003'....]}
...
]
Run Code Online (Sandbox Code Playgroud)
我在nodejs中有两种实现方式,它基于常规promise,另一种方法使用bluebird,如下所示
定期承诺
...
var groupsArray = [
{'G1': ['C1','C2','C3']},
{'G2': ['D1','D2','D3']}
]
function ajax(url) {
return new Promise(function(resolve, reject) {
request.get(url,{json: true}, function(error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
});
}
_.each(groupsArray,function(groupData){
_.each(groupData,function(contactlists,groupIndex){
// console.log(groupIndex)
_.each(contactlists,function(contactData){
ajax('http://localhost:3001/api/getcontactdata/'+groupIndex+'/'+contactData).then(function(result) {
console.log(result.body);
// Code depending on result
}).catch(function() {
// An error occurred
});
})
})
})
...
Run Code Online (Sandbox Code Playgroud)
使用bluebird方式我使用并发来检查如何控制promises队列
...
_.each(groupsArray,function(groupData){
_.each(groupData,function(contactlists,groupIndex){
var contacts = [];
// console.log(groupIndex)
_.each(contactlists,function(contactData){
contacts.push({
contact_name: 'Contact ' + contactData
});
})
groups.push({
task_name: 'Group ' + groupIndex,
contacts: contacts
});
})
})
Promise.each(groups, group =>
Promise.map(group.contacts,
contact => new Promise((resolve, reject) => {
/*setTimeout(() =>
resolve(group.task_name + ' ' + contact.contact_name), 1000);*/
request.get('http://localhost:3001/api/getcontactdata/'+group.task_name+'/'+contact.contact_name,{json: true}, function(error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
}).then(log => console.log(log.body)),
{
concurrency: 50
}).then(() => console.log())).then(() => {
console.log('All Done!!');
});
...
Run Code Online (Sandbox Code Playgroud)
我想知道什么时候使用promises处理内部循环中的1亿个api调用.请告知以异步方式调用API的最佳方法,稍后再处理响应.
我的答案使用常规 Node.js 承诺(这可能很容易适应 Bluebird 或其他库)。
您可以使用以下命令立即触发所有 Promise Promise.all:
var groupsArray = [
{'G1': ['C1','C2','C3']},
{'G2': ['D1','D2','D3']}
];
function ajax(url) {
return new Promise(function(resolve, reject) {
request.get(url,{json: true}, function(error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
});
}
Promise.all(groupsArray.map(group => ajax("your-url-here")))
.then(results => {
// Code that depends on all results.
})
.catch(err => {
// Handle the error.
});
Run Code Online (Sandbox Code Playgroud)
使用Promise.all尝试并行运行所有请求。当您有 5 亿个请求同时尝试时,这可能不会很好地工作!
一种更有效的方法是使用 JavaScriptreduce函数将您的请求一个接一个地排序:
// ... Setup as before ...
const results = [];
groupsArray.reduce((prevPromise, group) => {
return prevPromise.then(() => {
return ajax("your-url-here")
.then(result => {
// Process a single result if necessary.
results.push(result); // Collect your results.
});
});
},
Promise.resolve() // Seed promise.
);
.then(() => {
// Code that depends on all results.
})
.catch(err => {
// Handle the error.
});
Run Code Online (Sandbox Code Playgroud)
此示例将承诺链接在一起,以便下一个承诺仅在前一个承诺完成后才开始。
不幸的是,排序方法会非常慢,因为它必须等到每个请求完成后才能开始新的请求。当每个请求正在进行时(发出 API 请求需要时间),您的 CPU 处于空闲状态,而它可能正在处理另一个请求!
解决此问题的更有效但复杂的方法是使用上述方法的组合。您应该对请求进行批处理,以便并行执行每批(例如 10 个)中的请求,然后按顺序对各批进行排序。
自己实现这个功能很棘手 - 尽管这是一个很好的学习练习 - 使用Promise.all和reduce函数的组合,但我建议使用该库async-await-parallel。有很多这样的库,但我使用这个,它运行良好并且可以轻松完成您想要的工作。
您可以像这样安装该库:
npm install --save async-await-parallel
Run Code Online (Sandbox Code Playgroud)
以下是您将如何使用它:
const parallel = require("async-await-parallel");
// ... Setup as before ...
const batchSize = 10;
parallel(groupsArray.map(group => {
return () => { // We need to return a 'thunk' function, so that the jobs can be started when they are need, rather than all at once.
return ajax("your-url-here");
}
}, batchSize)
.then(() => {
// Code that depends on all results.
})
.catch(err => {
// Handle the error.
});
Run Code Online (Sandbox Code Playgroud)
这更好,但发出如此大量的请求仍然是一种笨拙的方式!也许您需要加大赌注并考虑投入时间进行适当的异步作业管理。
我最近一直在使用Kue来管理工作进程集群。将 Kue 与 Node.js 集群库结合使用可以让您在多核 PC 上获得适当的并行性,然后如果您需要更多的工作,您可以轻松地将其扩展到多个基于云的虚拟机。
请参阅我的回答此处获取一些 Kue 示例代码。