简体   繁体   English

解析云函数-依次执行代码ot

[英]Parse cloud function - code ot executed in sequence

I have below function to update rows if meeting some condition and at the end of for loop, response include how many rows updated.Despite more than zero rows updated, response shows zero. 我有下面的函数来更新行,如果满足某些条件,并且在for循环结束时,响应包括更新了多少行。尽管更新的行多于零,但响应显示为零。 Looking at log, it seems reponse.success() fires before completing for loop. 查看日志,似乎在完成for循环之前会触发reponse.success()。

why so? 为什么这样?

Parse.Cloud.define("reset", function(request, response) {


    var isSaveNeeded = false
  var Query = new Parse.Query("price");
  Query.equalTo('isActive', true);
  Query.find({useMasterKey:true})
      .then((results) => {
        console.log("Found " + results.length + " price rows")
        var currentDate = moment()
        var noOfRowsUpdated = 0
        for (let i = 0; i < results.length; ++i) {
            var valid_till_date = results[i].get('valid_till_date');

            if (valid_till_date == null) {
                // if user had not selected valid_till_date then set to expire after system max no of days
                var updatedAt = results[i].get('updatedAt');
                if (currentDate.diff(updatedAt,'days') > 10) {
                  console.log("Permanent change row to be set inactive. Updated at - " + currentDate.diff(updatedAt)+ updatedAt)
                    results[i].set('isActive',false)
                    isSaveNeeded = true
                }
            } else if (currentDate.diff(valid_till_date) > 0) {
                // check whether valid_till_date has passed
                console.log("Found row with elapsed valid date "  + results[i].id)
                results[i].set("isActive",false)
                isSaveNeeded = true
            }
            if (isSaveNeeded == true) {
              console.log("Record needs to be saved for " + results[i].id)
              results[i].save(null, {useMasterKey:true})
                .then(function (user) {
                    ++noOfRowsUpdated
                    console.log("reset : Object ID: " + results[i].id + " saved - " + noOfRowsUpdated)
                  })
                .catch(function (error) {
                    console.log("reset : Error saving Object ID: " + results[i].id + error);
                    response.error(error);
                })
            } else {

              console.log("Record not to be saved for " + results[i].id)
            }
            isSaveNeeded = false
        } // end of for loop
        //BELOW IS EXECUTED BEFORE FOR LOOP COMPLETES
        console.log("Updated " + noOfRowsUpdated +" price rows");
        response.success("Updated " + noOfRowsUpdated +" price rows")
      }) // end of .then((results) 
      .catch(function(error) {
        response.error("Failed to fetch from price" + error );
      });
});

Parse.com's save runs async, so that loop finishes before the saves happen. Parse.com的save异步运行,因此循环在保存发生之前完成。 The solution is to reorganize the code a little bit, and wait for the saves to happen before executing the response functions. 解决方案是稍微重组代码,并在执行响应功能之前等待保存完成。

The trick is to collect the promises returned by each save in an array and wait for the fulfillment of those promises with Promise.when() (synonym for Promise.all()) 诀窍是将每个保存的返回的诺言收集到一个数组中,并等待Promise.when()Promise.when()同义词Promise.when()实现这些诺言

To make it clearer, factor out the "is save needed" logic, so this cloud function can be only about handling the database... 为了更加清楚,请排除“需要保存”逻辑,因此该云功能只能用于处理数据库。

Parse.Cloud.define("reset", function(request, response) {
    var Query = new Parse.Query("price");
    Query.equalTo('isActive', true);
    Query.find({useMasterKey:true}).then((results) => {
        console.log("Found " + results.length + " price rows");
        // assuming ES6 or something like underscore
        let pricesToSave = results.filter(price => priceNeedsSave(price));

        // here's the important part, collect the promise from each save
        // proceed only after the promises have completed
        let promises =  pricesToSave.map(price => price.save(null, {useMasterKey:true}));
        return Parse.Promise.when(promises).then(() => pricesToSave.length);
    }).then(count => {
        response.success("Updated " + count +" price rows");
    }).catch(error => {
        response.error("Failed to fetch from price" + error );
    });
}

Just for completeness, below is the factored-out needsSave logic. 为了完整起见,下面是分解式的requireSave逻辑。 (OP should check this over, I just copied the body of the loop)... (OP应该检查一下,我只是复制了循环的主体)...

function priceNeedsSave(price) {
    var isSaveNeeded = false;
    var currentDate = moment()

    var valid_till_date = price.get('valid_till_date');
    if (valid_till_date == null) {
        // if user had not selected valid_till_date then set to expire after system max no of days
        var updatedAt = price.get('updatedAt');
        if (currentDate.diff(updatedAt,'days') > 10) {
          console.log("Permanent change row to be set inactive. Updated at - " + currentDate.diff(updatedAt)+ updatedAt)
            price.set('isActive',false)
            isSaveNeeded = true
        }
    } else if (currentDate.diff(valid_till_date) > 0) {
        // check whether valid_till_date has passed
        console.log("Found row with elapsed valid date "  + price.id)
        price.set("isActive",false)
        isSaveNeeded = true
    }
    return isSaveNeeded;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM