Promise.all откатывает действия успешных обещаний в случае неудачи

Я выполняю несколько обещаний со следующим фрагментом:

await Promise.all([promise1, promise2, promise3]);

Чего я хотел бы добиться, так это отменить последствия успешных промисов в случае отказа от Promise.all(). Говоря более конкретно, это означает, что описанное выше будет выполнять шифрование некоторых файлов, но если один из них не удастся, я хотел бы удалить другие два (или один) файла, которые были успешно зашифрованы, чтобы иметь согласованные и чистые группы файлов.

Из того, что я прочитал, это означает, что мне понадобятся два шага: 1. Отлавливать ошибки для каждого промиса, чтобы Promise.all() не выдавал ошибку. 2. Загадочная часть: иметь еще один вид Promise.all():

await Promise.all([rollbackPromise1, rollbackPromise2, rollbackPromise3]);

Это кажется сложной частью: должен ли я выполнять все откаты независимо от невыполненного обещания? Это означает, что я должен делать еще один перехват для каждой ошибки, чтобы Promise.all() ждал завершения каждого отката.

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

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
2
0
1 369
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете создать наивное решение следующим образом:

const errorHandlers = []
function enc1 () {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('str')
    }, 1000)
    errorHandlers.push(() => {
      console.log('handler 1')
    })
  })
}
function enc2 () {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('str')
    }, 2000)
    errorHandlers.push(() => {
      console.log('handler 2')
    })
  })
}
function enc3 () {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject('str')
    }, 3000)
    errorHandlers.push(() => {
      console.log('handler 3')
    })
  })
}

Promise.all([enc1(), enc2(), enc3()]).then(() => {
  console.log('all resovled')
}).catch((e) => {
  errorHandlers.forEach(handler => handler(e))
})

Это даст вам возможность обрабатывать «глобальную» ошибку в каждом промисе. Перед созданием обещания всех вы можете сбросить обработчики ошибок, чтобы предотвратить многократное выполнение обработчиков ошибок.

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

Ncifra 22.05.2019 15:54

"Если я не ошибаюсь"

Ncifra 22.05.2019 16:08
Ответ принят как подходящий

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

// Function that'll perform a promise.all and rollback if required
async function allWithRollback(promises) {
  // using the map we are going to wrap the promise inside of a new one
  return Promise.all(promises.map(([
    func,
    rollbackFunc,
  ], xi) => ((async() => {
    try {
      await func;

      console.log('One Function succeed', xi);
    } catch (err) {
      console.log('One Function failed, require rollback', xi);

      await rollbackFunc();
    }
  })())));
}

// Call the custom Promise.all
allWithRollback([
  [
    // First param is the promise
    okPromise(),

    // Second param is the rollback function to execute
    () => {},
  ],
  [okPromise(), () => {}],
  [errPromise(), rollback1],
  [errPromise(), rollback2],
  [okPromise(), () => {}],
]);

// ---------

async function okPromise() {
  return true;
}

async function errPromise() {
  throw new Error('no one read this');
}

async function rollback1() {
  console.log('Performed the rollback1');
}

async function rollback2() {
  console.log('Performed the rollback2');
}

Я предполагаю, что для rollback-s тоже будут okPromise()-s, если я правильно понимаю. Имеет смысл. Разумна ли такая логика (та, которую я использовал с откатами) при решении подобных проблем? Потому что у функций отката могут быть свои собственные сбои, поэтому нет никакого способа реально гарантировать выполнение. Есть ли смысл это делать, или это надо оставить делать вручную, и просто заметить как лог ошибок. Потому что позже у меня будет гораздо больше выполнений, которые могут завершиться неудачно, и включение откатов во все предыдущие откаты кажется немного излишним.

Ncifra 22.05.2019 15:51

Да, у okPromise() тоже есть свой откат. Добавление автоматического отката может быть целесообразным в зависимости от проблемы. Некоторые проблемы «ожидаются», и вам нужно с ними справиться. Когда это неожиданно, журнал и ручное лечение кажутся уместными. Все дело в контексте. Часто ли бывают ошибки? Насколько важным может быть ошибка? Должна ли доступность моей системы составлять 99,99%? Моя база данных будет повреждена в случае отсутствия отката?

Orelsanpls 22.05.2019 15:54

Другие вопросы по теме