重构:从值或现有承诺中返回承诺

Refactoring: returning a promise from a value or an existing promise

我的场景

我曾经使用 callbacks 完成一些 node.js 实现,但我现在正在重构我的代码以使用 Promises 代替 - 使用 Q 模块。我有以下 update() 函数,其中内部 _update() 函数已经 returns a Promise:

exports.update = function(id, template, callback) {
  if (!_isValid(template)){
    return callback(new Error('Invalid data', Error.INVALID_DATA));
  }

  _update(id, template) // this already returns a promise
  .then(function() {
    console.log('UPDATE was OK!');
    callback();
  }, function(err) {
    console.log('UPDATE with ERRORs!');
    callback(err);
  });
};

我的问题

我想实现 类似下面的东西:

exports.update = function(id, template) {
  if (!_isValid(template)){
    // how could I make it return a valid Promise Error?
    return reject(new Error('Invalid data', Error.INVALID_DATA));
  }

  return _update(id, template) // return the promise
  .done();
};

因为_update()已经returns一个promise,我想这样改就够了(不会吧?):

  return _update(id, template)
  .done();

而且...如果 if-clause 中的 condition 等于 true 呢?我该如何重构

return callback(new Error('Invalid data', BaboonError.INVALID_DATA));

抛出一个 error 以避免将 callback 传递给 update() 并处理该错误(或者任何可能返回的错误 _update())?

此外,调用 update():

myModule.update(someId, someTemplate)
.then(function() { /* if the promise returned ok, let's do something */ })
.catch(function(err) { /* wish to handle errors here if there was any */});

我代码中的其他地方:

我接近我的期望了吗?我怎么能最终实现它?

我只看到两个问题。

  1. 如果你想明确地 return 一个带有值的被拒绝的承诺,你应该使用 Q.reject.

  2. 在 promise 上调用 .done() 意味着 promise 到此结束。它无法进一步链接。

因此,您的代码将如下所示

exports.update = function (id, template) {
  if (!_isValid(template)) {
    return Q.reject(new Error('Invalid data', Error.INVALID_DATA));
  }

  return _update(id, template);
};

现在,update 功能 return 始终是一个承诺。由调用者将成功或失败处理程序附加到它。