组织承诺代码

Organize promise code

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

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

嗯,你可以把它分成功能:

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);

Promises 链,then 是对流量控制本身的抽象,您可以 return 来自另一个 promise 的 promise。更好的是,您可以使用协同程序来处理已经包含在书架中的蓝鸟:

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

我试着回答你的问题,请查看下面的代码

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