代码之家  ›  专栏  ›  技术社区  ›  Tim

jquery自定义事件和firefox 3.6.6和4.0 beta 1中的递归错误太多

  •  2
  • Tim  · 技术社区  · 16 年前

    我得到一个“太多递归”的错误。我将尝试对我的实际应用程序给出一个清晰的模拟,在那里发生了这个问题。

    想象一下,这个应用程序正在尝试调用一个WebService来获取关于一个非常长的货运列车内容的信息。有太多的信息,我们不能简单地调用WebService并告诉它在整个列车中同时发送关于每辆车的所有信息。相反,我们依次询问WebService关于每辆货车的信息,当收到关于单个货车的信息时,我们更新页面,然后询问下一辆车。

    为了保持客户机的响应,我们避免了循环,而是将事件与array.shift()一起使用:

    我们有一个活动:

    $('body').bind('NextBoxCar', function( e,  p) { getNexBoxCar(e,p);  });
    

    我们有一个函数,它从数组中删除第一个boxcarid并将其发送到WebService:

     EDIT: BoxCarIds is not a global but inside a function
     function() foo {
         var BoxCarIds = [123, 222, 767, 1234, 9298, ...  999];
         $('body').triggerHandler('NextBoxCar', BoxCarIds);
     }
    
     function getNextBoxCar(e, BoxCarIds) {      
    
       var id =  BoxCarIds.shift();
    
       // build an ajax request; omitted for brevity
         $.ajax( {
        .
        . <snip>
        .
         success:  function(data, textStatus, oHTTP ) {
            UpdatePage(data, BoxCarIds);
         }
       });
    
     }
    

    当BoxCar的数据从WebService返回时,Ajax成功处理程序调用以下函数,更新页面,然后触发NextBoxCar事件。我相信这就是递归问题发生的地方。

     function UpdatePage(data, BoxCarIds) {
    
         // update the page with data
          .
          . <snip>
          .
    
         // if there are still ids remaining in the array, we need to call the webservice again by firing the event
    
         if (BoxCarIds.length > 0 ) {
           $('body').triggerHandler('NextBoxCar', BoxCarIds);
    
         }
    
    
     }
    

    如何避免递归问题?

    谢谢

    4 回复  |  直到 16 年前
        1
  •  2
  •   EndangeredMassa    16 年前

    这里的递归部分对功能不重要。这只是Ajax调用的结果。您可以使Ajax调用同步并更改 getNextBoxCar 到一个循环但是,这仍然会使页面没有响应!

    所以,我认为你可以通过使用 setTimeout 调用UpdatePage方法。这应该打破递归,使页面保持响应。见 this jsFiddle example .

    尝试更改为:

    // build an ajax request; omitted for brevity
    $.ajax( {
        .
        . <snip>
        .
        success:  function(data, textStatus, oHTTP ) {
            setTimeout( function() {
                UpdatePage(data, BoxCarIds);
            }, 0);
        }
    });
    
        2
  •  2
  •   EndangeredMassa    16 年前

    你有 BoxCarIds 作为一个全局变量,但您也将它作为参数传递给 UpdatePage 和 getNextBoxCar . 所以,当你在里面的时候 更新页面 或 GETNEXBOXCARK ,您正在操作的本地版本 牛肝菌 不是全球性的!

    删除参数 牛肝菌 从 更新页面 和 GETNEXBOXCARK . 那么您的代码应该可以正常工作。

    下面是一个例子:

    var x = 3;
    
    function Eat(x)
        {
            x = 5;
        }
    
    alert(x); //alerts 3
    Eat(x);
    alert(x); //alerts 3
    

    但是,如果从EAT中删除参数,则会得到:

    var x = 3;
    
    function Eat()
        {
            x = 5;
        }
    
    alert(x); //alerts 3
    Eat(x);
    alert(x); //alerts 5
    
        3
  •  0
  •   Tim    16 年前

    我看不到“编辑”按钮,因此我必须对建议作出答复。无法格式化代码使其在注释中可读。

    我在问上面的问题时犯了错误。道歉。实际程序中的boxcarid不是全局的。程序如下:

     function getBoxCarIds(){
         .  
         .
         .
    
    
         var BoxCarIds = data;   // data is returned by webservice
         $('body').triggerHandler('NextBoxCar', BoxCarIds);   // kick things off
    
    
     }
    

    BoxCarids数组的长度实际上正在减小。当“货运列车”相当短时,程序运行良好。只有在列车长的时候才会遇到这种错误(例如140节车厢)。

        4
  •  0
  •   Tim    16 年前

    在jquery 1.4.2的第1936行,FF 3.6.6中发生了“过度递归”错误:

      // Filter the functions by class
     1929 if ( all || namespace.test( handleObj.namespace ) ) {
     1930 // Pass in a reference to the handler function itself
     1931 // So that we can later remove it
     1932 event.handler = handleObj.handler;
     1933 event.data = handleObj.data;
     1934 event.handleObj = handleObj;
     1935
     1936 var ret = handleObj.handler.apply( this, arguments );   // ERROR HERE
     1937
     1938 if ( ret !== undefined ) {
     1939 event.result = ret;
     1940 if ( ret === false ) {
     1941 event.preventDefault();
     1942 event.stopPropagation();
     1943 }
     1944 }
     1945
     1946 if ( event.isImmediatePropagationStopped() ) {
     1947 break;
     1948 }
     1949 }
     1950 }