清理Spaghetti Code w / Promises

时间:2016-01-28 01:28:50

标签: javascript parse-platform promise cloud-code

在我的一个beforeSave函数中,我需要在成功或错误响应之前检查一些条件。

问题是,我的代码看起来很乱,有时成功/错误也没有被调用:

Parse.Cloud.beforeSave("Entry", function(request, response) {
    var entry = request.object;
    var contest = request.object.get("contest");

    entry.get("user").fetch().then(function(fetchedUser) {
      contest.fetch().then(function(fetchedContest) {
            if ( fetchedUser.get("fundsAvailable") < fetchedContest.get("entryFee") ) {
              response.error('Insufficient Funds.');
            } else {
                fetchedContest.get("timeSlot").fetch().then(function(fetchedTimeSlot) {
                    var now = new Date();
                    if (fetchedTimeSlot.get("startDate") < now) {
                        response.error('This contest has already started.');
                    } else {
                        contest.increment("entriesCount");
                        contest.increment("entriesLimit", 0); //have to do this, otherwise entriesLimit is undefined in save callback (?)

                        contest.save().then(function(fetchedContest) {
                            if (contest.get("entriesCount") > contest.get("entriesLimit")) {
                                response.error('The contest is full.');
                            } else {
                                response.success();
                            }
                        });
                    }
                });
            }
        });
    });
});

我一直试图学习承诺来整理这件事,这是我的(失败的)尝试:

Parse.Cloud.beforeSave("Entry", function(request, response) {
    var entry = request.object;
    var contest = request.object.get("contest");

    entry.get("user").fetch().then(function(fetchedUser) {
        contest.fetch().then(function(fetchedContest) {
            if ( fetchedUser.get("fundsAvailable") < fetchedContest.get("entryFee") ) {
              response.error('Insufficient Funds.');
            }
            return fetchedContest;
        });
    }).then(function(result) {
        result.get("timeSlot").fetch().then(function(fetchedTimeSlot) {
            var now = new Date();

            if (fetchedTimeSlot.get("startDate") < now) {
                response.error('This contest has already started.');
            }
        });
    }).then(function() {
        contest.increment("entriesCount");
        contest.increment("entriesLimit", 0);
        contest.save().then(function(fetchedContest) {
            if (contest.get("entriesCount") > contest.get("entriesLimit")) {
                response.error('The contest is full.');
            }
        });
    }).then(function() {
        response.success();
    }, function(error) {
        response.error(error);
    });
});

任何有关如何使用promises的帮助或示例都将非常感激。很明显,我还没有完全理解它们在句法上是如何工作的。

2 个答案:

答案 0 :(得分:1)

你正在做的新错误是在链接它们时没有在.then内回复承诺,除非你的链仍然会继续,即使你打电话给response.error(..,最简单的方法来打破链条会引发错误,您的代码可以展平为:

Parse.Cloud.beforeSave("Entry", (request, response) => {
  var entry = request.object,
   , contest = request.object.get("contest")
   , fetchedUser
   , fetchedContest;

  entry.get("user").fetch()
    .then(_fetchedUser => {
      fetchedUser = _fetchedUser;
      return contest.fetch();
    }).then(_fetchedContest => {
      fetchedContest = _fetchedContest;
      if ( fetchedUser.get("fundsAvailable") < fetchedContest.get("entryFee") ) 
        return Promise.reject('Insufficient Funds.');      
      return fetchedContest.get("timeSlot").fetch();
    }).then(fetchedTimeSlot => {
      var now = new Date();
      if (fetchedTimeSlot.get("startDate") < now) 
        return Promise.reject('This contest has already started.');      
      contest.increment("entriesCount");
      contest.increment("entriesLimit", 0); //have to do this, otherwise entriesLimit is undefined in save callback (?)
      return contest.save();
    }).then(fetchedContest => {
      if (contest.get("entriesCount") > contest.get("entriesLimit")) 
        return Promise.reject('The contest is full.');          
      response.success();          
    }).catch(response.error.bind(response));

});

答案 1 :(得分:1)

我通过使用一系列承诺首先组装获取的变量来清理它。这遵循一些风格规则,使其更具可读性(无论如何)...

Parse.Cloud.beforeSave("Entry", function(request, response) {
    var entry = request.object;
    var contest = request.object.get("contest");

    var fetchedUser, fetchedContest;
    var errorMessage;

    entry.get("user").fetch().then(function(result) {
        fetchedUser = result;
        return contest.fetch();
    }).then(function(result) {
        fetchedContest = result;
        return fetchedContest.get("timeSlot").fetch();
    }).then(function(fetchedTimeSlot) {
        // now we have all the variables we need to determine validity
        var now = new Date();
        var hasSufficientFunds = fetchedUser.get("fundsAvailable") >= fetchedContest.get("entryFee");
        var contestNotStarted = fetchedTimeSlot.get("startDate") >= now;
        if (hasSufficientFunds && contestNotStarted) {
            contest.increment("entriesCount");
            contest.increment("entriesLimit", 0); //have to do this, otherwise entriesLimit is undefined in save callback (?)
            return contest.save();
        } else {
            errorMessage = (hasSufficientFunds)? 'This contest has already started.' : 'Insufficient Funds.';
            return null;
        }
    }).then(function(result) {
        if (!result) {
            response.error(errorMessage);
        } else {
            if (contest.get("entriesCount") > contest.get("entriesLimit")) {
                response.error('The contest is full.');
            } else {
                response.success();
            }
        }
    }, function(error) {
        response.error(error);
    });
});

请注意我们永远不会留下任何回复。任何东西()晃来晃去,我们总是通过回报明确表达了下一个承诺。