2013-07-12 90 views
1

我正在开发一个使用UWA小部件格式的javascript小部件。不幸的是,这使得不可能让js弄糟我的代码,但我已经详细地评论了它,希望你可以遵循它的相当简单的顺序。Internet Explorer的同步问题

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); 
    }); 
} 

本质的脚本执行以下操作:

  1. 检索的学生名单为每个类组
  2. 运行一个AJAX调用我们的PHP脚本/ MySQL数据库返回点的SUM对于这些学生
  3. 将名称和分数信息添加到对象数组
  4. 对对象数组进行排序,以便最高得分分数类是我们的第一个数组输入
  5. 显示类的名称,并从阵列进入他们的积分0

的问题是,我可以考虑一下这样做(因为这些API的限制)的唯一方法是运行异步API调用和连锁AJAX呼吁这些。然后我使用计数变量来确定最后一次异步调用的时间。

现在,重要的是,这个脚本在FireFox中工作得很好。但是,在Internet Explorer中 - 这是我需要它工作的地方 - 脚本显示我们的“加载”DIV /图像,并且不再进一步。

奇怪的是,如果我在代码中填入alert(我用大写字母评论它),Internet Explorer将正常工作。

这必须是一个同步性和时机问题,但我没有经验或知识。

任何人都可以提出解决方案吗?如果有必要,Hacky很好。

干杯,

回答

1

,一个警报“修复”的问题确实表明,它的东西做的一个计时问题的事实。它看起来像你的一个函数没有及时返回,也没有正确地填充数组变量。

尝试使计数和结束变量全局并看看是否有帮助。我认为这与范围有关。

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); 
     }); 

HighestClass.array是当HighestClass.display();被称为除非你等待你的Ajax调用来完成空。您可以使您的ajax调用同步,或将此HighestClass.display();放入Ajax回调中。

2

首先是:/!\当使用回调模式时,您的“流量”需要在回调函数中重新开始。

我可以看到你在异步和回调方法方面有问题。当你$ .getJSON的时候,而且每次你​​做一个青蛙。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) { 

不会通过。所以什么都不会发生,你的显示将尝试获取未定义对象的值=>错误,JavaScript停止,不会更新视图。 您需要在onSuccess回调中检索列表后获取JSON。这会有所帮助,因为你之后犯了同样的错误:

在接下来你要求有一个显示器,但你绝对不知道你的电话是否完成。它要求最后一次通话的事实并不意味着任何通话都已完成。

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>'); 
     } 
    }); 
}