我正在运行一系列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");
}
*/
});
答案 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 */);