node.js - Nodejs 使用 async.parallel & async/wait。有没有更好的方法来做到这一点
问题描述
是一种更好的方法,下面的代码有效,我想做的是,
- 读取 schedule.json 文件
- 同步处理每个主计划
- 子计划可以并行运行
const async = require('async');
const schedule = {
"scheduleA": {
"JobA":"a.bat 1000",
"JobB":"b.bat 800"
},
"scheduleB":{
"JobC":"c.js 600"
},
"scheduleC":{
"JobD":"d.js 400"
},
"scheduleD": {
"JobE":"e.bat 200",
"JobF":"f.js 0"
}
};
var wait = (job, sleepTime) =>{
return new Promise(function(resolve, reject){
setTimeout( ()=>{
resolve(job+' - Completed');
}, sleepTime);
});
}
var executeSchedule = (sched, jobs) =>{
return new Promise(function(resolve, reject) {
console.log('Processing Schedule : '+sched);
let stack = [];
let keys1 = Object.keys(jobs);
for(let i=0; i<keys1.length; i++){
let temp = jobs[keys1[i]].split(' ');
console.log('executeSchedule : '+temp);
stack.push(function(callback){ callback(null,wait(temp[0], temp[1])) });
}
async.parallel(stack,function(err,result){
if (err) {
console.log(err);
reject(err);
}
console.log("Before Results are: " + result);
Promise.all(result).then( resp =>{
console.log("After Results are: " + resp);
resolve(resp);
});
});
});
}
const start = ()=>{
return new Promise(async function(resolve, reject) {
let results = [];
let keys1 = Object.keys(schedule);
console.log(keys1);
for(let i=0; i<keys1.length; i++){
let sr = await executeSchedule(keys1[i], schedule[keys1[i]]);
results.push(sr);
}
resolve(results);
});
}
start().then( resp =>{
console.log('Response : '+JSON.stringify(resp, null, 2));
}).catch( err => {
console.log('Error : '+err);
});
最终将用 child_process/spawn/exec 功能替换 wait(),这将触发 Windows 中的 .bat 和 .js 程序。
我想知道的是,
- 有没有更好的方法来编写程序,最初想到的是 async.series 来处理主要的计划(目前在 start() 中使用的是 async/await)。
- 目前我在executeSchedule中使用的是async.parallel,也可以使用async.map。但是我想知道的是,在不使用异步库(或)这里的异步库的情况下,是否有任何更简单更好的本机 nodejs 方式更适合。
解决方案
您可以使用承诺链来做到这一点。
要序列化,只需要实现“下一个”函数或使用可迭代对象,对于 Parallel,您只需使用Promise.all
.
请注意评论中所说的“显式 Promise 构造反模式”,因为它会增加巨大的性能开销。
这是一个工作示例,从以下位置开始:
const schedule = {
"scheduleA": {
"JobA": "a.bat 1000",
"JobB": "b.bat 800"
},
"scheduleB": {
"JobC": "c.js 600"
},
"scheduleC": {
"JobD": "d.js 400"
},
"scheduleD": {
"JobE": "e.bat 200",
"JobF": "f.js 0"
}
};
var wait = (job, sleepTime) => {
return new Promise(function (resolve) {
setTimeout(() => { resolve(job + ' - Completed'); }, sleepTime);
});
}
var executeSchedule = (sched, jobs) => {
console.log('Processing Schedule : ' + sched);
const stack = Object.values(jobs).map(script => {
const args = script.split(' ');
return wait(args[0], args[1])
})
return Promise.all(stack)
.then(resp => {
// NOTE: this .then is useless
console.log("After Results are: " + resp);
return resp
});
}
const start = async () => {
const serial = Object.entries(schedule)
const results = []
const next = async () => {
if (serial.length > 0) {
const [key, value] = serial.shift()
const out = await executeSchedule(key, value)
results.push(out)
return next()
}
return results
}
return next()
}
start()
.then(results => {
console.log('Response : ' + JSON.stringify(results, null, 2));
})
.catch(err => {
console.log('Error : ' + err);
});
推荐阅读
- java - 将属性加载到 InputStream
- javascript - 情绪和不和谐的反应
- ruby-on-rails - Rails 5.2.1 - 模型和片段缓存
- php - Laravel 4.2 走错路了
- powershell - 无法通过 Powershell 找到证书:驱动器或证书提供程序
- aerospike - 在没有索引的情况下看到具有 4G 的 memory_used_index_bytes
- c# - 在 Roslyn Fixer 中获取样式设置
- sql-server - BCP 实用程序 - 忽略导入文件中的默认值
- javascript - 用于添加到购物车的 redux concat 数组
- python - 使用两个或多个不同的键查找 django 模型