Цикл Javascript обещает синхронно с дополнительным параметром - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть массив обещаний, которые я пытаюсь выполнить одно за другим

function asyncInsertMagFromFile(file, resolve) {
            //some asynchronous processing with file
            resolve();
          }

let magRequests = fs.readdirSync(storeDir).map(function(file) {
            return new Promise(resolve => {
              asyncInsertMagFromFile(file, resolve);
            });
          });

Я пытаюсь обработать эти обещания (magRequests) "синхронно", но безуспешно.Существует множество вопросов по этому вопросу, но я не нашел ни одного, который соответствовал бы моей проблеме.Я попробовал некоторые из решений Trincot здесь https://stackoverflow.com/a/40329190/7531001, но я не знаю, как обрабатывать мой параметр файла.

Например, это не работает (ожидание допустимо только в асинхронной функции)

(async function loop() {
            fs.readdirSync(storeDir).forEach(function(file) {
              await new Promise(resolve =>
                asyncInsertMagFromFile(file, resolve)
              );
            });

          })();

Есть идеи, как мне это исправить?

Ответы [ 5 ]

0 голосов
/ 20 февраля 2019

Если вы хотите обрабатывать последовательно и обрабатывать результат, вы можете использовать рекурсию:

const FAILED = {};
const processImages = (files) => {
  const recur=(files,result) => {
    if(files.length===0){
      return result;
    }
    return asyncInsertMagFromFile(files[0])
    .catch(error=>FAILED)//always resolve, place FAILED values when rejected
    .then(success=>recur(files.slice(1),result.concat(success)))
  }
  return recur(files,[])
}

processImages(fs.readdirSync(storeDir)).then(results=>{
  console.log('failed',results.filter(r=>r===FAILED).length)
});

Для параллельной обработки вы можете использовать Promise.all:

Promise.all(
  fs.readdirSync(storeDir).map((file)=> asyncInsertMagFromFile(file).catch(FAILED))
).then(results=>{
  console.log('failed',results.filter(r=>r===FAILED).length)
})
0 голосов
/ 20 февраля 2019

Это может вам помочь;

async function asyncInsertMagFromFile(file) {
 // use await to gather results from processing or return a promise
 return result;
}

function mapRequests(storeDir) {
  return fs.readdirSync(storeDir).map(async function(file) {
    return await asyncInsertMagFromFile(file);
  });
}

mapRequests(storeDir).then((mapped) => {});

Причина, по которой ваш пример не сработал, заключается в том, что функция обработчика forEach использует await, но не объявлена ​​как асинхронная.

0 голосов
/ 20 февраля 2019

ожидание действует только в асинхронной функции

Используйте .map вместо .forEach и передайте ему асинхронную функцию в качестве обратного вызова.

0 голосов
/ 20 февраля 2019

Вы можете связать несколько 'затем один за другим.

function asyncInsertMagFromFile(file) {
    return new Promise((resolve, reject) => {
        //some asynchronous processing with file
        // call resolve when finished
        resolve();
    })
}

let chain = Promise.resolve();

fs.readdirSync(storeDir).forEach(function (file) {
    chain = chain.then(((file) => () => asyncInsertMagFromFile(file))(file));
});

chain.then(() => {
    //finished
}).catch((err) => {
   //error in chain
})

Другой способ - использовать оператор for, как указано в комментариях:

function asyncInsertMagFromFile(file) {
    return new Promise((resolve, reject) => {
        //some asynchronous processing with file
        // call resolve when finished
        resolve();
    })
}

(async () => {
    const files = fs.readdirSync(storeDir);

    for (let i = 0; i < files.length; i++) {
        await asyncInsertMagFromFile(files[i]);
    }
})()
0 голосов
/ 20 февраля 2019

Вы можете попытаться использовать array.reduce, чтобы получить предыдущее значение (список обещаний) и дождаться его завершения, прежде чем делать очередной вызов функции asyncInserMagFromFile

(function loop() {
  fs.readdirSync(storeDir).reduce(async (previousPromise, file) => {
    await previousPromise;
    return new Promise(resolve =>
      asyncInsertMagFromFile(file, resolve);
    );
  },Promise.resolve());
})();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...