我有一个for循环,它遍历一个关联数组。 foreach条目我必须发出ajax请求并用检索到的数据填充另一个数组 问题是成功回调是异步的,所以它只在循环迭代后运行。这意味着我的数据数组中填充了最后一个ajax请求结果的多个副本。 这是我的代码(简化):
var channels = {
"misured": "channel_misured",
"plan": "channel_plan"
};
var data; //Initial data is empty
function getData() {
data = new Array();
for (var seriesData in channels) {
var currentData = new Array();
$.ajax({
type: "GET",
url: 'http://' + serverAddress + ':' + serverPort + '/GetChannelBufferAsJsonp?channelName=' + channels[seriesData] + '&callback=?',
dataType: "json",
async: false,
success: function (json) {
var time = new Date().getTime() + 3600000;
for (var i = 0; i < json.length; i++) {
currentData.push({
x: time + i * 30000,
y: json[i]
});
}
data.push({
id: seriesData,
name: "Production " + seriesData,
data: currentData
});
}, error: function () {
console.log("error", this);
}
});
}
}
所以数据有2个元素(正确),但它们都来自“plan_channel”(这是我的数据源)。
我知道这是ajax请求的经典,众所周知的“问题”(或特征),但我看不出如何摆脱它。
你能说出如何在进入下一次迭代之前等待成功回调结束吗?
答案 0 :(得分:1)
这是我能看到重构代码的唯一方法(在我的头顶)。虽然它有点无意义。你已经设置了所有错误的IMO,你不应该这样做。我能看到的最好的方法是将整个数组发送到一个ajax请求到ajax脚本,在php(或其他)中处理所有这些并在javascript中以你想要的格式将它吐出来。否则你最好找到一个更好的方法来做到这一点。例如,您可以拥有一个ajax请求,而不是拥有for循环,该请求会在成功调用中回调getData()
函数。
// add a global var...
var inLoop;
function getData() {
data = new Array();
for (var seriesData in channels) {
inLoop = true; // set to true
var currentData = new Array();
$.ajax({
type: "GET",
url: 'http://' + serverAddress + ':' + serverPort + '/GetChannelBufferAsJsonp?channelName=' + channels[seriesData] + '&callback=?',
dataType: "json",
async: false,
success: function (json) {
// set inLoop to false to get out of loop below
inLoop = false;
var time = new Date().getTime() + 3600000;
for (var i = 0; i < json.length; i++) {
currentData.push({
x: time + i * 30000,
y: json[i]
});
}
data.push({
id: seriesData,
name: "Production " + seriesData,
data: currentData
});
}, error: function () {
console.log("error", this);
}
});
// loop round this bit for a while
while(inLoop){
// wait
}
}
}
这就是我重写上面代码的方法:
var channels = {
"first" : "hello world",
"second" : "goodbye world"
}
function getData(channel){
$.ajax({
url: 'http://whatever.com/channel='+channel,
success: function(){
getData(nextchannel);
}
});
}
为了做到这一点,你可能需要计算你通过函数或其他东西的时间,以便能够再次将下一个通道传递给函数。
答案 1 :(得分:1)
对于同步AJAX调用,您无法使用成功处理程序,并且必须在调用完成后返回结果。
尝试使用Amplify.js(http://amplifyjs.com/),asyc设置为false;它比jQuery ajax功能更易于使用和更整洁。不要被附加图书馆推迟。
更新#1
你只需要这样做
function getData() {
data = new Array();
for (var seriesData in channels) {
var currentData = new Array();
amplify.request.define( "ajaxExample1", "ajax", {
url: 'http://' + serverAddress + ':' + serverPort + '/GetChannelBufferAsJsonp?channelName=' + channels[seriesData] + '&callback=?',
dataType: "json",
async: false,
type: "GET"
});
// later in code
amplify.request( "ajaxExample1", function( json ) {
var time = new Date().getTime() + 3600000;
for (var i = 0; i < json.length; i++) {
currentData.push({
x: time + i * 30000,
y: json[i]
});
}
data.push({
id: seriesData,
name: "Production " + seriesData,
data: currentData
});
});
}
}