Javascript返回循环总和

时间:2016-04-14 23:20:31

标签: javascript each .post

我正在运行一系列3个ajax帖子,最后我需要在每个循环中对while循环中的设备求和。首先我得到会话ID,然后我得到设备的数量,并做一个foreach循环来获取每个设备的ID。在那之后我做一个循环,从开始日期到今天日期每月增加并获得设备月消费和总和。我需要将所有设备的总消耗量一起消耗几个月。

我在函数的中间做了评论,我可以求和,并且我得到值0.我甚至尝试运行一个单独的函数,它在最后的注释中,但它仍然保持返回未定义。

希望你能理解这个想法。

var SESSION_ID ='';
var total = parseFloat(0.0);
$.post("http://xxx.xxxxxxxx.com/users/auth", {
    token : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    }, function (session) {
        if(session) {
            console.log("Session id received.");
            SESSION_ID = session.id;
            console.log("Looking for devices.");
            $.post("http://xxx.xxxxxxxxxxxxxxx.com/devices/list", {
                id : session.id
            }, function (devices) {
                if(devices) {

                    /* Loop trough devices to get id of each device */
                    $.each(devices, function(index, val) {

                         /* Set start date */
                        var targetDate = new Date();
                        targetDate.setFullYear(2015);
                        targetDate.setMonth(2);
                        targetDate.setDate(1);
                        targetDate.setHours(0);
                        targetDate.setMinutes(0);
                        targetDate.setSeconds(0);
                        var currentDate = new Date();

                        /* Increase 1 month until current date */
                        while (targetDate.getMonth() !== currentDate.getMonth() || targetDate.getFullYear() !== currentDate.getFullYear()) {
                            //console.log("Month: " + (targetDate.getMonth() + 1) + "; Year: " + targetDate.getFullYear());
                            var month = targetDate.getMonth() + 1,
                                year = targetDate.getFullYear();

                            $.post("http://xxx.xxxxxxxxxxxxxx.com/devices/" + val.id + "/consumptions?year=" + year + "&month=" + month + "&resolution=month", {
                                id : SESSION_ID
                            }, function (consumptions) {
                                if(consumptions) {
                                    $.each(consumptions, function(index, val) {
                                         /* Sum each month consumption value */
                                         if(val.value !== '') {
                                            total += val.value;
                                         }
                                    });

                                    // Return values float values Eg.: 11774.86060142517 and keeps
                                    console.log(total);
                                }
                            }, "json");
                            // Increase month
                            targetDate.setMonth(targetDate.getMonth() + 1);

                            // console.log(total) returns 0
                            console.log(total);
                        }
                    });

                    // Total returning 0
                    // console.log(total);
                } else {
                    console.log("No devices found.");
                }
            }, "json");
        } else {
            console.log("No session id");
        }
    }, "json");

    /*
    function getMonthConsumption(device_id, device_year, device_month) {
        $.post("http://xxx.xxxxxxxxxxxxxx.com/devices/" + device_id + "/consumptions?year=" + device_year + "&month=" + device_month + "&resolution=month", {
            id : SESSION_ID
        }, function (consumptions) {
            if(consumptions) {
                $.each(consumptions, function(index, val) {

                     if(val.value !== '') {
                        total = total + val.value;
                     }
                });
                return consumptions;
            }
        }, "json");
    }
    */
});

1 个答案:

答案 0 :(得分:1)

$.post循环中每月每次设备消耗所做的while是异步的,因此代码执行会一直持续到你得到0的打印部分。如果你将值记录到控制台在所有帖子后,您将看到结果已正确计算。要在您的示例中看到这一点,请删除所有console.log调用,并将行total += val.value;替换为添加到全局值的函数,并在控制台中记录新值,例如:

function addToTotal(value) {
  total += value;
  console.log(total);
}

...
/* Sum each month consumption value */
if(val.value !== '') {
  addToTotal(val.value);
}
...

要检测所有帖子何时完成然后计算总和,您可以使用jQuery promise,因为$ .post方法已经返回一个。看看jQuery.when()

修改

基于这里的评论是一个提出的jQuery承诺解决方案。 首先添加一系列承诺,您将保留所有消费请求,然后收集所有响应并处理它们:

var SESSION_ID ='';
var total = parseFloat(0.0);

$.post("http://xxx.xxxxxxxx.com/users/auth", {
    token : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    }, function (session) {
        if(session) {
            console.log("Session id received.");
            SESSION_ID = session.id;
            console.log("Looking for devices.");
            $.post("http://xxx.xxxxxxxxxxxxxxx.com/devices/list", {
                id : session.id
            }, function (devices) {
                if(devices) {

                    var promises = [];

                    /* Loop trough devices to get id of each device */
                    $.each(devices, function(index, val) {

                         /* Set start date */
                        var targetDate = new Date();
                        targetDate.setFullYear(2015);
                        targetDate.setMonth(2);
                        targetDate.setDate(1);
                        targetDate.setHours(0);
                        targetDate.setMinutes(0);
                        targetDate.setSeconds(0);
                        var currentDate = new Date();

                        /* Increase 1 month until current date */
                        while (targetDate.getMonth() !== currentDate.getMonth() || targetDate.getFullYear() !== currentDate.getFullYear()) {
                            //console.log("Month: " + (targetDate.getMonth() + 1) + "; Year: " + targetDate.getFullYear());
                            var month = targetDate.getMonth() + 1,
                                year = targetDate.getFullYear();

                            var postPromise = $.post("http://xxx.xxxxxxxxxxxxxx.com/devices/" + val.id + "/consumptions?year=" + year + "&month=" + month + "&resolution=month", {
                                id : SESSION_ID
                            }, "json");
                            promises.push(postPromise);

                            // Increase month
                            targetDate.setMonth(targetDate.getMonth() + 1);
                        }
                    });

                    // Gather all responses
                    $.when.apply($, promises).then(function() {
                        var total = 0;
                        // Here arguments will have the responses from all $.post requests added to the promises array. The actual respo
                        $.each(arguments, function(index, jqueryPostResponses) {

                            var consumptions = jqueryPostResponses[0] // first object is the data;

                            $.each(consumptions, function(index, val) {
                                /* Sum each month consumption value */
                                if(val.value !== '') {
                                    total += val.value;
                                }
                            });

                        });

                        return total;
                    }).then(doSomethingWithTotal);

                } else {
                    console.log("No devices found.");
                }
            }, "json");
        } else {
            console.log("No session id");
        }
    }, "json");

    function doSomethingWithTotal(totalSum) {
        $('#totalSum').text(totalSum);
    }
});

由于我无法在不知道实际响应的情况下测试此代码,因此您可能需要调整代码才能使其正常工作。这是一个有用的JSFiddle来帮助您。

对于循环执行,将$.post包含在将使用setInterval(theNewFunction, 1000 /* repeat interval in ms */);

运行的新函数中的设备中