Promise.all откат успешных обещаний действия на провал - PullRequest
2 голосов
/ 22 мая 2019

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

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

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

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

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

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

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

Ответы [ 2 ]

1 голос
/ 22 мая 2019

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

// 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');
}
0 голосов
/ 22 мая 2019

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

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))
})

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

...