Javascript返回循环和

Javascript Return loop sum

本文关键字:循环 返回 Javascript      更新时间:2023-09-26

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

我在函数中间做了注释,在这里我可以求和,在这里得到值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");
    }
    */
});

while循环中,您每月为每个设备消耗所做的$.post是异步的,因此代码执行一直持续到打印部分,在那里您得到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);
}
...

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

编辑

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

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 */); 运行的新函数中