首页 > 解决方案 > Nodejs 使用 async.parallel & async/wait。有没有更好的方法来做到这一点

问题描述

是一种更好的方法,下面的代码有效,我想做的是,

  1. 读取 schedule.json 文件
  2. 同步处理每个主计划
  3. 子计划可以并行运行
    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 程序。

我想知道的是,

  1. 有没有更好的方法来编写程序,最初想到的是 async.series 来处理主要的计划(目前在 start() 中使用的是 async/await)。
  2. 目前我在executeSchedule中使用的是async.parallel,也可以使用async.map。但是我想知道的是,在不使用异步库(或)这里的异步库的情况下,是否有任何更简单更好的本机 nodejs 方式更适合。

标签: node.jsasync-awaitasync.js

解决方案


您可以使用承诺链来做到这一点。

要序列化,只需要实现“下一个”函数或使用可迭代对象,对于 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);
  });

推荐阅读