Разрешение массива обещаний параллельно с обработкой ошибок - PullRequest
0 голосов
/ 18 апреля 2020

У меня есть коллекция обещаний или асинхронных c функций, мне нужно немного манипулировать и затем выполнять параллельно.

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

// Some dummy tasks:
const taskA = () => Promise.resolve(500);
const taskB = () => {
  return new Promise(resolve => resolve(300));
};

// Push them into an array:
const tasks = [];

const registerTask = (name, task) => {
  tasks.push( async () => { 
    return { [name]: await task() };
  });
};

// trying to get the results
const runTasks = () => {
  const result = Promise.all(tasks).then(results => results);
  return result;
}

// usage
registerTask('taskA', taskA);
registerTask('taskB', taskB);

console.log(runTasks())

После успешного разрешения обещаний в идеале я бы также хотел обрабатывать ошибки индивидуально для каждой задачи.

Ответы [ 2 ]

1 голос
/ 18 апреля 2020

Promise.all ожидает массив обещаний, и вы передаете массив функций, который возвращает обещание . Поэтому измените ваше обещание Promise.all, чтобы получить обещание каждой функции:

// Some dummy tasks:
const taskA = () => Promise.resolve(500);
const taskB = () => {
  return new Promise(resolve => resolve(300));
};

// Push them into an array:
const tasks = [];

const registerTask = (name, task) => {
  tasks.push( async () => { 
    return { [name]: await task() };
  });
};

// trying to get the results
const runTasks = () => {
  const result = Promise.all(tasks.map(task => task())); // Execute the tasks to receive the promises
  return result;
}

// usage
registerTask('taskA', taskA);
registerTask('taskB', taskB);

runTasks().then((res) => {console.log(res)})
1 голос
/ 18 апреля 2020

Проблема в том, что ваша функция registerTask помещает функции в массив tasks, а не Promise объекты. Если вы измените функцию следующим образом, она должна работать:

const registerTask = (name, task) => {
  const asyncFunc = async () => { 
    return { [name]: await task() };
  };
  tasks.push( asyncFunc() ); // This pushes a promise into 'tasks'
};

В результате ваш оригинальный код tasks стал массивом функций, которые еще не были вызваны. Когда вы вызываете Promise.all(tasks), он немедленно заканчивается undefined для каждой записи в массиве, поскольку не было Promise объектов, ожидающих ожидания.

Что касается обработки ошибок, Promise.all завершится с ошибкой первое отклонение или исключение, которое случается. Если вы хотите обработать отдельный случай ошибки каждой задачи, то вы должны сделать это в Promise, созданном в registerTask, поскольку делать это во время Promise.all слишком поздно. Трудно привести пример, так как я не уверен, какой тип обработки ошибок подходит для задач, но, возможно, что-то вроде этого:

const registerTask = (name, task) => {
  const asyncFunc = async () => { 
    return { [name]: await task() };
  };
  const promise = asyncFunc()
    .catch(err => {
      return handleError(name, err);
    });
  tasks.push( promise ); 
};

function handleError(name, err) {
  console.log(`Task ${name} had error ${err}`);
  // don't re-throw the error if you want all tasks to complete
  // return some error object so you can see which tasks failed after they're done
  return {error: err, name: name};  
}
...