【问题标题】:Organize promise code整理承诺代码
【发布时间】:2016-04-25 11:18:57
【问题描述】:

我有以下代码。但这看起来类似于回调地狱。我如何将这段代码重新组织成更合适的承诺方式

   FacilityBooking.forge({
            "booking_id": req.params.id
        })
        .fetch({
            require: true
        })
        .then(function(collection) {
            if(0) { //@todo check if admin
                throw new NotAuthorised(CFG_MESSAGES.error[403]);
            } else {
                Bookshelf.transaction(function(t) {
                    collection
                        .save({
                            "is_valid": 0,
                            "updated_by": req.user.id
                        }, {transacting: t})
                        .tap(function(model) {
                            new FacilityBooking(model.toJSON())
                                 .save({
                                    "is_valid": 1,
                                    "reason_for_reject": req.body.disapprovereason || '' ,
                                    "status": approval_status[req.body.moderation_action]
                                }, {transacting: t})
                                .then(function(collection) {
                                    res.json({
                                        status: true,
                                        message: CFG_MESSAGES.facility_booking.moderate.success
                                    });
                                })
                                .catch(function(err) {
                                    res.json({
                                        status: false,
                                        message: CFG_MESSAGES.facility_booking.moderate.error
                                    });
                                });
                        });
                });
            }
        })
        .catch(function(err) {
            ErrorHandler.handleError(res, err);
        });

【问题讨论】:

  • 为什么要内联所有内容?
  • 看看 enrmarc 的回答。
  • 为什么使用tap 而不是then
  • 难道transaction 不希望您回调到return 是一个承诺吗?它本身会返回一个承诺吗?
  • Removing nested promises 的可能重复项

标签: javascript promise bluebird bookshelf.js


【解决方案1】:

好吧,你可以把它分成函数:

var onErrorProcessingBooking = function(err) {
  ErrorHandler.handleError(res, err);
};

var tap = function(model) {

  var onSuccessSave = function(collection) {
    res.json({
      status: true,
      message: CFG_MESSAGES.facility_booking.moderate.success
    });
  };

  var onErrorSave = function(err) {
    res.json({
      status: false,
      message: CFG_MESSAGES.facility_booking.moderate.error
    });
  };

  new FacilityBooking(model.toJSON())
    .save({
      "is_valid": 1,
      "reason_for_reject": req.body.disapprovereason || '',
      "status": approval_status[req.body.moderation_action]
      }, {    
      transacting: t
    })
    .then(onSuccessSave)
    .catch(onErrorSave);
}

var onSuccessProcessingBooking = function(collection) {
  if (0) {
     throw new NotAuthorised(CFG_MESSAGES.error[403]);
     return;
  }

  Bookshelf.transaction(function(t) {
    collection
      .save({
       "is_valid": 0,
       "updated_by": req.user.id
       }, {
        transacting: t
      })
      .tap(tap);
  });
}


FacilityBooking
  .forge({"booking_id": req.params.id})
  .fetch({require: true})
  .then(onSuccessProcessBooking)
  .catch(onErrorProcessingBooking);

【讨论】:

    【解决方案2】:

    Promises 链,then 是对流控制本身的抽象,您可以从另一个 Promise 返回一个 Promise。更好的是,您可以使用协程来处理已经包含在书架中的 bluebird:

    const forger = Promise.coroutine(function*() {
      const collection = yield FacilityBooking.forge({ "booking_id": req.params.id })
                                              .fetch({ require: true });    
      if(0) throw new NotAuthorised(CFG_MESSAGES.error[403]);
      yield Bookshelf.transaction(Promise.coroutine(function *(t) {
        yield collection.save({
          "is_valid": 0,
          "updated_by": req.user.id
        }, {transacting: t});
          const model =  new FacilityBooking(model.toJSON());
          yield model.save({
            "is_valid": 1,
            "reason_for_reject": req.body.disapprovereason || '' ,
            "status": approval_status[req.body.moderation_action]
        }, {transacting: t});
        res.json({
          status: true,
          message: CFG_MESSAGES.facility_booking.moderate.success
        });
      }));
    }).catch(function(err) {
      // filter error here, and do the res.json with the failure here
      if(isRelevantError) {
        res.json({
          status: false,
          message: CFG_MESSAGES.facility_booking.moderate.error
        });
      }
      ErrorHandler.handleError(res, err);
    });
    

    【讨论】:

    • 这如何使流程减少“回调地狱”?使用生成器对这个问题没有帮助。
    • @elad.chen 你是什么意思? OPs 代码没有正确处理异常并且无缘无故地嵌套 - 此代码没有遇到任何问题。
    • 忽略我的评论。读得太快了。
    • 请不要 es6。你能给我一个 es5 吗?你的代码对我来说有点难以理解
    • Node 是基于 ES2015 构建的,你可以在 Node 中使用它,不用担心任何问题。另外,哪个部分难以遵循?您是否阅读了 bluebird 网站上的 Promise.coroutine 文档?
    【解决方案3】:

    我试图回答你的问题,请检查下面的代码

    Bookshelf.transaction(function(t) {
           FacilityBooking.forge({
                   "booking_id": req.params.id
               })
               .fetch({
                   require: true
               })
               .then(function(collection) {
                   if(0) { //@todo check if admin
                       throw new NotAuthorised(CFG_MESSAGES.error[403]);
                   } else {
                       return collection
                           .save({
                               "is_valid": 0,
                               'updated_by': req.user.id
                           }, {
                               transaction: t,
                               patch: true
                           });
                   }
               })
               .then(function(model) {
                   var data = model.toJSON();
                   delete data.id;
                   return new FacilityBooking(data)
                           .save({
                               "is_valid": 1,
                               "reason_for_reject": req.body.disapprovereason || 'bbbbbbbbbbb' ,
                               "status": approval_status[req.body.moderation_action]
                           }, {
                               transaction: t,
                               method: 'insert'
                           })
               })
               .then(function(collection) {
                   res.json({
                       status: true,
                       message: CFG_MESSAGES.facility_booking.moderate.success
                   });
               })
               .catch(function(err) {
                   res.json({
                       status: false,
                       message: CFG_MESSAGES.facility_booking.moderate.error
                   });
               })
       });
    

    【讨论】:

      猜你喜欢
      • 2016-12-11
      • 2019-08-29
      • 2016-01-08
      • 2015-03-14
      • 2017-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      相关资源
      最近更新 更多