Javascript Return 循环求和
Javascript Return loop sum
我是 运行 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 的打印部分。如果您记录该值在所有 post 之后到控制台,您将看到结果已正确计算。要在您的示例中看到这一点,请删除所有 console.log
调用并将行 total += val.value;
替换为添加到全局值并在控制台中记录新值的函数,例如:
function addToTotal(value) {
total += value;
console.log(total);
}
...
/* Sum each month consumption value */
if(val.value !== '') {
addToTotal(val.value);
}
...
要检测所有 post 何时完成,然后计算总和,您可以使用 jQuery 承诺,因为 $.post 方法已经 returns 一个。看看 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 */);
我是 运行 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 的打印部分。如果您记录该值在所有 post 之后到控制台,您将看到结果已正确计算。要在您的示例中看到这一点,请删除所有 console.log
调用并将行 total += val.value;
替换为添加到全局值并在控制台中记录新值的函数,例如:
function addToTotal(value) {
total += value;
console.log(total);
}
...
/* Sum each month consumption value */
if(val.value !== '') {
addToTotal(val.value);
}
...
要检测所有 post 何时完成,然后计算总和,您可以使用 jQuery 承诺,因为 $.post 方法已经 returns 一个。看看 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 */);