如何在数组的每个项目上正确地使异步任务列表同步

时间:2019-02-11 15:29:27

标签: javascript node.js asynchronous

我需要以同步方式执行多项任务。 从文件夹及其子文件夹中提取一些文件到一组项目中,然后对其进行临时复制。 这两个任务我设法同步完成。

然后,我需要在数组的每个项目上执行7个任务,并且我需要等待7个任务完成一项,然后再传递到下一个任务。

但是我所做的每一次尝试都以以下顺序结束任务: 例如要处理3个文件:

1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 6 7 6 7 6 7.我希望是: 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4 5 6 7 最后两个任务堆叠在一起,并且仅在为每个文件都执行5个“第一”任务时才触发。

在这里,我如何启动脚本:

start();

async function start() {
    await listDirToProcess(); // This works
    await makeSafeCopy(); // This works as well
    for (var currentDCF of dirToProcess) {
        Perform the 7 tasks... 
    }
}

我尝试了一个回调地狱(上一个任务的回调中的所有事情) 我尝试了没有start()函数 我尝试了或多或少的异步/等待关键字 我还尝试了在SO中找到的asyncForEach函数,而不是当前的for-of循环:

async function asyncForEach(array, callback) {
    for (let index = 0; index < array.length; index++) {
        await callback(array[index], index, array);
    }
}

但是他们都没有成功。

我目前正在使用for(yy的xx)循环遍历数组。

以下是这些任务的摘要:
步骤1 : 将文件复制到另一个文件夹,我就是这样:

// Usage of the function 
await copyToSomeDir(stuff, (err) => {
    err == 0 ?
        log.info('\t\tCopy to xxx went well') :
        log.info('\t\tCopy to xxx ended with ' + err + " error ");
    });
// Definition of the function
function copyToSomeDir(item, cb) { // Notice i didn't put the async key word
    ...
    cb(i);
}

第2步: 等待外部应用在Step 1输出文件夹上完成工作

// Usage of the function 
await execExternJob();
// Definition of the function
function execExternJob() {
    log.info("Executing Talend job")
    child_process.execSync(cmd_to_exe, (error, stdout, stderr) => {
        log.info("job completed for the " + item.entity);
    })
}

第3步: 检查上一个外部作业的结果:

// Usage of the function 
await checkSuccessfulJob(xxx, (list) => {
    ...
    });
// Definition of the function
function checkSuccessfulJob(xxx, cb) {
    ...
    cb(list);
}

第4步: 用其他文件替换一些文件

// Usage of the function 
await OverwriteSucessFile(currentDCF.talendResult.success);
// Definition of the function
function OverwriteSucessFile(list) {
    ...
};

!!! 这是打破一切的步骤。 !!! 步骤5-6-7: 如果在外部工作期间一切都不顺利,那就做些事情 其他压缩文件夹并将其上传到Web服务(实际上是CMS)。

if (fault) {
   fault.forEach((faultyFile) => {
       ... // Not important
   })
} else {
//Usage of the function 
    await prepareZipFolder(xxx, yyy, (path) => { // Step 5
        getUrlFromFile(AlfrescoUrl, (url) => { // Step 6
            uploadToCMS(url, path (ok) => { // Step 7
                        log...
                    })
                });
            });
}

这是我认为是有问题的功能的定义:

async function prepareZipFolder(zipFileName, rootZipFolder, callback) {
    var zipFile = fs.createWriteStream(path.join(rootZipFolder, zipFileName) + ".zip");
    // >>>>>>>>>>>   Here is where it pass to the next itteration instead of waiting the end of the archiving. I think !     <<<<<<<<<<<
    var archive = archiver('zip', {
        zlib: { level: 9 } // Sets the compression level.
    });
    zipFile.on('close', () => {
        callback(path.join(rootZipFolder, zipFileName) + ".zip")
    })
    zipFile.on('open', (fd) => {
        archive.on('error', function (err) { log.info(err) });
        archive.pipe(zipFile);
        archive.glob("**", { cwd: path.join(rootZipFolder, zipFileName) }, { prefix: zipFileName });
        archive.finalize();
    })
}

问题在于,当创建.zip fil时,循环传递到下一个项目,而不是等待归档结束。

很长的问题很抱歉,有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

如果我正确理解,您会不断地将promisized函数与回调函数混合使用(还会发生一些奇怪的事情,例如child_process.execSync(cmd_to_exe, (error, stdout, stderr) => {...Sync函数不使用回调函数,但这可能是一个错字)。

您需要坚持一种方法。如果某些API不提供返回Promise的功能,则仅在它们之前添加await便不会与Promise兼容。您需要自己寻找另一个API或实现包装函数的功能。

例如,您的第2步:

await execExternJob();

function execExternJob() {
    log.info("Executing Talend job")
    child_process.execSync(cmd_to_exe, (error, stdout, stderr) => {
        log.info("job completed for the " + item.entity);
    })
}

可以改写为:

await execExternJob();

function execExternJob() {
  log.info("Executing Talend job");

  return new Promise((resolve, reject) => {
    child_process.exec(cmd_to_exe, (error, stdout, stderr) => {
      if (error) {
        reject(error);
      } else {
        log.info("job completed for the " + item.entity);
        resolve();
      }
    });
  });
}

以此类推。