ES6承诺解决回调?

mpe*_*pen 43 javascript ecmascript-6 es6-promise

无论我的Promise是否成功解决,我都希望运行相同的操作.我不想将同一个函数绑定到两个args .then.是不是.always像jQuery一样?如果没有,我该如何实现?

Ber*_*rgi 34

是不是.always像jQuery一样?

不,还没有.虽然有一个积极的提案,所以也许E​​S2018.

如果没有,我该如何实现?

您可以finally像这样自己实现该方法:

Promise.prototype.finally = function(cb) {
    const res = () => this
    const fin = () => Promise.resolve(cb()).then(res)
    return this.then(fin, fin);
};
Run Code Online (Sandbox Code Playgroud)

或者更广泛地说,将解析信息传递给回调:

Promise.prototype.finally = function(cb) {
    const res = () => this
    return this.then(value =>
        Promise.resolve(cb({state:"fulfilled", value})).then(res)
    , reason =>
        Promise.resolve(cb({state:"rejected", reason})).then(res)
    );
};
Run Code Online (Sandbox Code Playgroud)

两者都确保原始分辨率得以维持(当回调中没有异常时)并且等待承诺.

  • 我认为在pollyfill中`this.then`的错误回调应该抛出而不是返回. (2认同)
  • 你的第一个实现(没有值)似乎与[规范](https://github.com/tc39/proposal-promise-finally)一致,所以这很好:-) (2认同)

Lee*_*son 9

使用async/await,您可以组合await使用try/finally,如下所示:

async function(somePromise) {
  try {
    await somePromise();
  } finally {
    // always run this-- even if `somePromise` threw something
  }
}
Run Code Online (Sandbox Code Playgroud)

这是我使用Babel的async-to-generator插件在Node生产中运行的一个真实示例.

// Wrap promisified function in a transaction block
export function transaction(func) {
  return db.sequelize.transaction().then(async t => {
    Sequelize.cls.set('transaction', t);
    try {
      await func();

    } finally {
      await t.rollback();
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

我在Sequelize ORM旁边的mocha测试中使用此代码来启动数据库事务,无论测试中的数据库调用结果如何,总是在最后回滚.

这大致类似于Bluebird的.finally()方法,但IMO,更好的语法!

(:在你想知道为什么我不区分await第一承诺-荷兰国际集团是Sequelize的实现细节它使用.CLS为"捆绑" SQL事务的无极链凡是招,里面同样链范围内的任何东西都没有.因此,等待Promise会"关闭"事务块并打破链条.我把这个例子放进去向你展示如何将"vanilla"Promise处理与异步函数混合在一起,并在一起玩得很好.)