【问题标题】:Prevent promise chain to go next step [duplicate]防止承诺链进行下一步[重复]
【发布时间】:2016-01-05 20:38:06
【问题描述】:

首先,我想问一下,这对于使用 Promise 是否是一个很好的解决方案。

app.get('/sample', function(req, res) {

var promiseFlow = {

    step1: function() {
        return modelPromise1();
    },

    step2: function(result) {
        if(result) {
            // I would like to stop the promise chain here
            res.send(result);
        } else {
            return modelPromise2();
        }
    },

    step3: function(result) {
        if(result) {
            res.send(result);
        } else {
            // This will be sent always
            res.send(false);
        }
    }

}

promiseFlow.step1()
    .then(promiseFlow.step2)
    .then(promiseFlow.step3)
    .catch(function(error) {
        console.log(error);
    });

});

用户模型示例:

_self.get_user_info = function(_guid) {
var deferred = modules.Q.defer();

modules.system.db.connect(deferred, function(connection) {
    var query = modules.qb.select().from('users')
                    .field('_guid')
                    .field('username')
                    .where('_guid = ?', _guid);

    connection.query(query.toString(), function(error, result) {
        connection.release();
        if(error) {
            deferred.reject(error);
            return; 
        }
        if(result.length) {
            deferred.resolve(result);
        } else {
            deferred.reject(null);
        }

    });
});
return deferred.promise;

}

我的主要问题是我不知道如何打破链条 执行下一步。 res.send(false) 无论如何都会在第 3 步发生。 这东西可以工作吗,或者我应该为此选择其他模式。

谢谢!

【问题讨论】:

    标签: javascript node.js promise q


    【解决方案1】:

    我认为问题在于您正在以相反的方式接近它。 成功时应兑现承诺,错误时应拒绝。

    then方法有两个参数:第一个是处理成功,第二个是处理拒绝。在拒绝时,控制流跳转到下一个拒绝处理程序 - 在履行时,它只是转到下一个履行处理程序。通常我更喜欢catch,因为它更清楚地处理了谁的错误。

    看起来您正在尝试将成功(当您发送响应时)作为错误处理,反之亦然。 你应该在错误而不是成功时打破链条。

    此外,您的承诺应该在错误时被拒绝(例如,在失败时抛出异常,或拒绝承诺),而不是仅仅不返回结果。

    你需要这样的东西:

    promise1()
      .then(function(result) {
        res.send(result);
      }, function(error) {
        return promise2()
          .then(function(result) {
            res.send(result);
          }, function(result) {
            res.send(false);
          });
      });
    

    【讨论】:

    • 我的第一种方法有点像这样,但这导致我尝试避免使用金字塔代码。让我稍微解释一下我的代码结构。我有一个用户模型,其中包含返回承诺的 mysql 查询。如果我得到结果,我会解决承诺,并且只有在连接出现错误时才会拒绝承诺。因此,如果我按照您建议的方式正确,我需要将该模型方法调用包装到另一个承诺中并处理结果以使我的模型保持原始状态。或者如果拒绝模型的方法承诺,即使它是错误或糟糕的结果,我也会想到另一种方法
    • 拒绝不仅仅是错误 - 它是关于没有得到你“承诺”返回的数据。如果你的模型方法返回一个数据的承诺,你可以在出现错误或该数据不可用时拒绝它。在后一种情况下,您可以返回一个后备承诺(在示例中为 promise2),而在前一种情况下,您可以重新抛出错误,以便在处理每个错误的catch 中捕获。你是对的,这必须在你的模型中实现,但你不必为它创建一个包装器,你可以在它之后链接一个 then 来处理它
    【解决方案2】:

    这实际上并没有什么不同,但会使代码复杂化。

    试试这个:

    modelPromise1()
      .then(function(result) {
        if (!result) return modelPromise2();
      }).then(function(result) {
        if (!result) res.send(false);
        else res.send(result);
      }).catch(/*...*/);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-28
      • 2018-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-16
      • 2015-01-10
      • 1970-01-01
      相关资源
      最近更新 更多