我正在使用UWA小部件格式开发一个javascript小部件。不幸的是,这使得jsFiddle我的代码变得不可能,但我已经对它进行了详细的评论,希望你可以按照相当简单的顺序进行。
HighestClass = {};
HighestClass.array = [];
HighestClass.url = "http://our.url.local/frog/pointsByWeek.php?cmd=highestClass&students=";
HighestClass.init = function(groupPrefix) {
var count = 0;
/* Using the group prefix, i.e. "CLS 9", from the drop-down box,
get a list of all of the classes in that year group */
/* First time round, count the number of groups that match this
syntax because there are no parameters available to filter
this API */
Frog.API.get('groups.getAll',{
'onSuccess': function(data){
for (var i = 0; i < data.length; i++) {
if (data[i].name.indexOf(groupPrefix) != -1)
count++;
}
});
/* Now that these classes have been counted, run through the API
call again to push each class ID through to another function */
var run_through = 0;
Frog.API.get('groups.getAll',{
'onSuccess': function(data){
for (var i = 0; i < data.length; i++) {
if (data[i].name.indexOf(groupPrefix) != -1) {
var end = false;
run_through++;
/* When it gets to the last class group, i.e. the run_through
variable becomes equal to count, let the getClassPoints
function know */
if( run_through == count )
end = true;
HighestClass.getClassPoints( data[i].name, data[i].id, end );
}
}
}
});
}
HighestClass.getClassPoints = function(name, id, end) {
var list = '';
/* Using the ID of the class group, create a comma-separated list
of students for use in our MySQL query */
Frog.API.get("users.search", {
"params": {
"group": id
},
"onSuccess": function (data){
for (var i = 0; i < data.length; i++)
list += data[i].id + ",";
}
});
/* If the list exists... */
if( typeof list === "string" && list.length > 0 ) {
list = list.slice(0,-1);
/* Run an AJAX call to our PHP script which simply returns an integer
value of the SUM of reward points earned by that list of students */
UWA.Data.getJson(HighestClass.url + list, function(res){
if (res === false || res === "") res = 0;
/* Push this data into an array of objects alongside the class name */
var obj = { "name": name, "points": res };
HighestClass.array.push(obj);
});
}
/* As this function is being called asynchronously multiple times we need to
determine when the last call is run so that we can deal with our array
of data. We do this thanks to the count/run_through variables in earlier
function which will trigger end=true in this function */
if( end === true )
HighestClass.display();
}
HighestClass.display = function() {
/* Once we've put our array of objects together, we need to sort it so that
the class with the highest number of points are at array entry 0 */
function compare(a,b) {
if (a.points < b.points)
return 1;
if (a.points > b.points)
return -1;
return 0;
}
/* IF I PUT AN ALERT HERE, INTERNET EXPLORER WORKS, LOL? */
HighestClass.array.sort(compare);
/* We can then display the data of array entry 0 which should be our highest
point-scoring class */
$('#display').html( '<h1>' + HighestClass.array[0].name + '</h1><h3>' + HighestClass.array[0].points + '</h3>' );
}
/* equivalent of document ready */
widget.onLoad = function(){
/* Choose the year group from the drop down box */
$("select").change(function(){
var val = $('select option:selected').val();
$("#display").html('<h1><img width="60" height="60" src="http://logd.tw.rpi.edu/files/loading.gif" />Loading...</h1>');
HighestClass.init(val);
});
}
本质上,脚本执行以下操作:
问题是,我能想到的唯一方法(由于API的限制)是运行异步API调用和链接AJAX调用。然后我使用计数变量来确定最后一次异步调用的时间。
现在,重要的是,此脚本在FireFox中运行良好。但是,在Internet Explorer中 - 这是我需要它工作的地方 - 脚本显示我们的“加载”DIV /图像并且不再进一步。
奇怪的是,如果我在代码中添加了alert
(我用大写字母对其进行了评论),Internet Explorer就可以正常工作。
这必须是同步性和时间安排的问题,但我没有经验或知识。
有人可以提出解决方案吗?如果有必要,Hacky很好。
干杯,
答案 0 :(得分:2)
首先是: /!\当使用回调模式时,您的“流程”需要在回调函数中重新开始。
我可以看到你遇到了异步和回调方法的问题。当您使用$ .getJSON但每次进行Frog.API调用时,例如:
Frog.API.get("users.search", {
"params": {
"group": id
},
"onSuccess": function (data){
for (var i = 0; i < data.length; i++)
list += data[i].id + ",";
}
});
在这里,您可以检索数据,并将它们放在带有onSuccess回调函数的列表中。我的猜测是这个调用也是异步的。如果此通话耗时太长:
if( typeof list === "string" && list.length > 0 ) {
不会通过。所以什么都不会发生,你的显示器会尝试获取未定义对象的值=&gt;错误,JavaScript停止,没有更新您的视图。 在onSuccess回调中检索列表后需要getJSON。这将有所帮助,因为你在犯下同样的错误之后:
接下来你要求有一个显示器,但你绝对不知道你的电话是否完成。它要求最后一次通话的事实并不意味着任何通话都已完成。
if( end === true )
HighestClass.display();
所以你只需要在以下后添加:
HighestClass.array.push(obj);
在$ .getJSON调用中。
Ajax调用通常异步,您的问题是您尝试与当前流同步更新显示,而无需等待服务器回答。 /!\当使用回调模式时,您的“流”需要在回调函数中重新开始。使用它,您将始终确保您运行的代码具有所需的所有数据实现它的职责。
PS:这是修改过的所有代码。我还修改了你的函数init。您无需再次调用API来重做同样的事情。只需在数据上循环两次,或者将唯一的相关数据放在一个数组中,然后在其上循环。
HighestClass = {};
HighestClass.array = [];
HighestClass.url = "http://our.url.local/frog/pointsByWeek.php?cmd=highestClass&students=";
HighestClass.init = function(groupPrefix) {
/* Using the group prefix, i.e. "CLS 9", from the drop-down box,
get a list of all of the classes in that year group */
Frog.API.get('groups.getAll',{
'onSuccess': function(data){
var i = 0,
l = 0,
count = 0,
group = [];
/* First time round, count the number of groups that match this
syntax because there are no parameters available to filter
this API */
for (i = 0, l = data.length; i < l; i++) {
if (data[i].name.indexOf(groupPrefix) != -1)
group.push(data[i]);
}
/* Now that these classes have been counted, run through the API
call again to push each class ID through to another function */
l = group.length;
count = l - 1;
for (i = 0; i < l; i++) {
// i == count will be true when it is the last one
HighestClass.getClassPoints( group[i].name, group[i].id, i == count);
}
});
}
HighestClass.getClassPoints = function(name, id, end) {
/* Using the ID of the class group, create a comma-separated list
of students for use in our MySQL query */
Frog.API.get("users.search", {
"params": {
"group": id
},
"onSuccess": function (data){
var list = '';
// We have data and build our string
for (var i = 0; i < data.length; i++)
list += data[i].id + ",";
/* If the list exists... */
if( typeof list === "string" && list.length > 0 ) {
list = list.slice(0,-1);
/* Run an AJAX call to our PHP script which simply returns an integer
value of the SUM of reward points earned by that list of students */
UWA.Data.getJson(HighestClass.url + list, function(res){
if (res === false || res === "") res = 0;
/* Push this data into an array of objects alongside the class name */
var obj = { "name": name, "points": res };
HighestClass.array.push(obj);
/* As this function is being called asynchronously multiple times we need to
determine when the last call is run so that we can deal with our array
of data. We do this thanks to the count/run_through variables in earlier
function which will trigger end=true in this function */
if( end === true )
HighestClass.display();
});
}
}
});
}
HighestClass.display = function() {
/* Once we've put our array of objects together, we need to sort it so that
the class with the highest number of points are at array entry 0 */
function compare(a,b) {
if (a.points < b.points)
return 1;
if (a.points > b.points)
return -1;
return 0;
}
/* IF I PUT AN ALERT HERE, INTERNET EXPLORER WORKS, LOL? */
HighestClass.array.sort(compare);
/* We can then display the data of array entry 0 which should be our highest
point-scoring class */
if (HighestClass.array.length > 0)
$('#display').html( '<h1>' + HighestClass.array[0].name + '</h1><h3>' + HighestClass.array[0].points + '</h3>' );
else
$('#display').html( '<h1>No data available</h1>' );
}
/* equivalent of document ready */
widget.onLoad = function(){
/* Choose the year group from the drop down box */
$("select").change(function(){
var val = $('select option:selected').val();
$("#display").html('<h1><img width="60" height="60" src="http://logd.tw.rpi.edu/files/loading.gif" />Loading...</h1>');
try {
HighestClass.init(val);
} catch (e) {
$("#display").html('<h1>Sorry, an error occured while retrieving data</h1>');
}
});
}
答案 1 :(得分:1)
警报“修复”问题的事实确实表明它与计时问题有关。看起来你的一个函数没有及时返回而没有正确填充数组变量。
尝试将计数和结束变量全局化并查看是否有帮助。我认为这与范围有关。
答案 2 :(得分:1)
这很可能是因为你的Ajax调用在这里是异步的:
UWA.Data.getJson(HighestClass.url + list, function(res){
if (res === false || res === "") res = 0;
/* Push this data into an array of objects alongside the class name */
var obj = { "name": name, "points": res };
HighestClass.array.push(obj);
});
除非您等待ajax调用完成,否则和HighestClass.array
在调用HighestClass.display();
时为空。您可以使ajax调用同步或将此HighestClass.display();
放入Ajax回调中。