Как правильно составить синхронный список асинхронных задач для каждого элемента массива - PullRequest
0 голосов
/ 11 февраля 2019

Мне нужно выполнить несколько задач синхронно.Извлеките некоторые файлы из папки и ее подпапок в массив элементов, а затем сделайте временную копию всех из них.Эти две задачи мне удалось выполнить синхронно.

Затем мне нужно выполнить 7 задач для каждого элемента массива, и мне нужно подождать, пока задача 7 будет завершена для одной, прежде чем перейти кследующий.

Но каждая моя попытка заканчивалась выполнением задач в следующем порядке: пример для обработки 3 файлов:

1 2 3 4 5 1 2 3 4 5 1 2 3 4 56 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 (), которую я пытался использовать с более или менее асинхронными / ожидающими ключевыми словами, я также пытался использовать функцию asyncForEach, которую я нашел в SO вместо текущего цикла for-of:

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

Но ни одно из нихсделал трюк.

В настоящее время я использую цикл for (xx of yy), чтобы пройти через tМассив.

Вот краткое изложение этих задач:
Шаг 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: Подождитечтобы внешнее приложение могло выполнить задание в выходной папке шага 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: Если не все прошло хорошо во время внешней работы, сделайте что-нибудь еще, заархивируйте папку и загрузите ее в веб-службу (на самом деле 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 голосов
/ 12 февраля 2019

Если я правильно понимаю, вы постоянно смешиваете обещанные функции с функциями обратного вызова (также происходят некоторые странные вещи, такие как child_process.execSync(cmd_to_exe, (error, stdout, stderr) => {... - Sync функции не используют обратные вызовы, но это может быть опечаткой).

Вы должны придерживаться одного подхода.Если некоторые API не предоставляют функции, которые возвращают Promise, эти функции не станут совместимыми с Promise, если вы просто добавите await перед ними.Вам нужно найти другой 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();
      }
    });
  });
}

И т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...