在jquery.each()
内使用jquery.getJSON
功能时遇到问题。
在这种情况下,我在代码中处理了两种类型的元素。 “来源”和“流”
我想使用getJSON
来获取源代码,迭代它们并从中生成一个手风琴标题。然后,对于每个“源”,我再次使用getJSON
与该源的id来获取它的相应“流”。然后我将这些流附加到它的源手风琴主体,以获得所有流的列表,按其来源排序。
但是当我得到JSON时,我的程序中的下一个语句已经执行了。因为我基本上是动态构建一个大的HTML String并使用jQuery将它添加到一个元素,所以String不能获得它需要的所有数据。
代码如下:
var html1 = "<div class='panel-group' id='manageAccordion'>";
$.getJSON(url, function(data){
$.each(data, function(i, json){
html1 += getAccordionPart(...); //creates the accordion for the given source
});
}).done(function(){
html1 += "</div>";
$('#elementList').html(html);
});
function getAccordionPart(id, parent, count, json){
//new string html2 is created and a bunch of stuff added
//...
html2 += "....";
html2 += getAccordionBody(json);
html2 += "</div></div></div></div>";
return html2
}
function getAccordionBody(json){
//new string "html3" gets created
//...
var url = standardUrl + "sources/" + encodeURIComponent(json.elementId) + "/streams";
$.getJSON(url, function(data) {
$.each(data, function(i, json) {
html3 += "<li class='list-group-item'>";
html3 += json.name;
html3 += "</li>";
});
}).done(function(){
html3 += "</ul>";
return html3;
});
}
我最后得到的是一个手风琴标题,它的身体“未定义”,
因为在将html字符串添加到DOM之前,getAccordionBody()
函数似乎没有返回。
我已尝试在$.getJSON
两次调用中将$.ajax
更改为async = false
$.getJSON
,这似乎解决了语句不执行的问题按照我希望他们的顺序,但它的速度非常慢,无论如何都会因为某些原因而返回undefined ..
有什么建议吗? 我错过了一些非常愚蠢的东西吗?
答案 0 :(得分:1)
似乎getAccordionBody()函数在将html字符串添加到DOM之前没有返回
那是对的。你return
ing the response (html3
) from ajax的方式存在缺陷 - 你不能return
来自done
处理程序。
然而,你可以通过使用promises来解决这个问题。每个函数都返回一个promise,以便它们很容易链接,then
用于转换数据并获得新的承诺:
$.getJSON(url).then(function(data){
return $.when.apply($, $.map(data, function(i, json){
return getAccordionPart(…); //creates the accordion for the given source
}).then(function() {
var html1 = "<div class='panel-group' id='manageAccordion'>";
html1 += Array.prototype.join.call(arguments, "\n");
html1 += "</div>";
return html1;
});
}).done(function(html){
$('#elementList').html(html);
});
function getAccordionPart(id, parent, count, json){
return getAccordionBody(json).then(function(result) {
var html2 = "…"; //new string html2 is created and a bunch of stuff added
html2 += result;
html2 += "</div></div></div></div>";
return html2;
});
}
function getAccordionBody(json) {
var url = standardUrl + "sources/" + encodeURIComponent(json.elementId) + "/streams";
return $.getJSON(url).then(function(data) {
var html3 = "…"; //new string "html3" gets created
$.each(data, function(i, json) {
html3 += "<li class='list-group-item'>";
html3 += json.name;
html3 += "</li>";
});
html3 += "</ul>";
return html3;
});
}
答案 1 :(得分:0)
您可以使用延迟/承诺模式 - http://api.jquery.com/deferred.promise/。
,而不是使用同步调用答案 2 :(得分:0)
您必须首先收集全局数组中“getAccordionPart”和“getAccordionBody”(例如:encodeURIComponent(json.elementId))所需的所有内容。像:
var arrIds = [];
$.getJSON(url, function(data){
$.each(data, function(i, json){
arrIds.push(encodeURIComponent(json.elementId))//collect everything which is required for "getAccordionPart" and "getAccordionBody"
});
然后迭代这个集合,并在任何全局变量中收集这些id的手段主体的所有数据。
var bodyData = {};
$.each(arrIds, function(){
var url = standardUrl + "sources/" + this + "/streams";
$.getJSON(url, function(data) {
bodyData[this] = data;//collect all the Data for accordian body of these ids
}});
也可以在getAccordionPart中进行更改,例如:
function getAccordionPart(id, parent, count, /*json*/ elementId){
//new string html2 is created and a bunch of stuff added
//...
html2 += "....";
html2 += getAccordionBody(elementId);
html2 += "</div></div></div></div>";
return html2
}
也改变了getAccordionBody:
function getAccordionBody(/*json*/ elementId){
//new string "html3" gets created
//...
var data = bodyData[elementId];
$.each(data, function(i, json) {
html3 += "<li class='list-group-item'>";
html3 += json.name;
html3 += "</li>";
});
html3 += "</ul>";
return html3;
}
您的通话也将更改:
$.each(arrIds , function(){
html1 += getAccordionPart(,,,this); //creates the accordion for the given source
});
你最终的代码将是:
var arrIds = [];
$.getJSON(url, function(data){
$.each(data, function(i, json){
arrIds.push(encodeURIComponent(json.elementId))//collect everything which is required for "getAccordionPart" and "getAccordionBody"
});
var bodyData = {};
$.each(arrIds, function(){
var url = standardUrl + "sources/" + this + "/streams";
$.getJSON(url, function(data) {
bodyData[this] = data;//collect all the Data for accordian body of these ids
}});
function getAccordionPart(id, parent, count, /*json*/ elementId){
//new string html2 is created and a bunch of stuff added
//...
html2 += "....";
html2 += getAccordionBody(elementId);
html2 += "</div></div></div></div>";
return html2
}
function getAccordionBody(/*json*/ elementId){
//new string "html3" gets created
//...
var data = bodyData[elementId];
$.each(data, function(i, json) {
html3 += "<li class='list-group-item'>";
html3 += json.name;
html3 += "</li>";
});
html3 += "</ul>";
return html3;
}
$.each(arrIds , function(){
html1 += getAccordionPart(,,,this); //creates the accordion for the given source
});