Promise.all回滚成功的诺言对失败采取的行动

时间:2019-05-22 12:45:02

标签: javascript node.js error-handling promise async-await

我正在使用以下代码段执行多个promise:

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

我想实现的是回退成功承诺对Promise.all()失败的影响。 用更具体的术语来说,这意味着上述操作将对文件进行一些加密,但是如果其中一个失败,我想删除另外两个(或一个)已成功加密的文件,以使文件组保持一致且干净。

根据我的阅读,这意味着我需要两个步骤: 1.捕获每个承诺的错误,以使Promise.all()不会引发错误。 2.令人困惑的部分:还有另一种Promise.all()

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

这似乎是棘手的部分:我是否应该独立于失败的诺言执行所有回滚?这意味着我应对每个错误进行另一个捕获,以使Promise.all()等待每次回滚完成。

这是执行此操作的最佳方法,我发现它在代码方面非常低效且难看。

2 个答案:

答案 0 :(得分:1)

您可以创建自己的函数,以实现对函数的异步调用并在需要时执行回滚。

// 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');
}

答案 1 :(得分:0)

您可以如下创建一个简单的解决方案:

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