Пользовательские события jQuery и слишком много ошибок рекурсии в Firefox 3.6.6 и 4.0 beta 1 - PullRequest
2 голосов
/ 11 июля 2010

Я получаю ошибку "слишком много рекурсии".Я постараюсь дать четкий аналог моего фактического приложения, где эта проблема возникает.

Представьте, что приложение пытается вызвать веб-службу, чтобы получить информацию о содержимом очень длинного грузового поезда.Существует так много информации, что мы не можем просто вызвать веб-службу и сказать ей, чтобы она отправляла все сразу за каждую машину во всем поезде.Скорее, мы спрашиваем веб-сервис о каждом грузовом вагоне по очереди, и когда получаем информацию об одном вагоне, мы обновляем страницу и затем запрашиваем следующий вагон.

Чтобы клиент оставался отзывчивым, мы избегаем зацикливания и используем вместо него события с array.shift ():

У нас есть событие:

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

У нас естьфункция, которая удаляет первый boxcarid из массива и отправляет его веб-службе:

 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 возвращаются из веб-службы, обработчик успеха 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 ]

2 голосов
/ 12 июля 2010

Рекурсивная часть здесь не важна для функциональности.Это просто следствие вызовов ajax.Вы можете сделать вызовы ajax синхронными и изменить getNextBoxCar на цикл.Тем не менее, это все равно оставит страницу без ответа!

Итак, я думаю, что вы можете исправить проблему, используя setTimeout для вызова метода UpdatePage.Это должно нарушить рекурсию и оставить страницу отзывчивой.См. этот пример jsFiddle .

Попробуйте перейти на это:

// build an ajax request; omitted for brevity
$.ajax( {
    .
    . <snip>
    .
    success:  function(data, textStatus, oHTTP ) {
        setTimeout( function() {
            UpdatePage(data, BoxCarIds);
        }, 0);
    }
});
2 голосов
/ 11 июля 2010

У вас есть BoxCarIds как глобальная переменная, но вы также передаете ее в качестве параметра UpdatePage и getNextBoxCar.Поэтому, когда вы находитесь внутри UpdatePage или getNextBoxCar, вы управляете локальной версией BoxCarIds, а не глобальной!

Удалите параметр BoxCarIds из UpdatePage и getNextBoxCar,Тогда ваш код должен работать нормально.

Ниже приведен пример:

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
0 голосов
/ 11 июля 2010

Ошибка «слишком много рекурсии» происходит в FF 3.6.6 в строке 1936 в jquery 1.4.2:

  // 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 } 
0 голосов
/ 11 июля 2010

Я не вижу кнопку Изменить, поэтому мне придется ответить на предложения с ответом.Нет способа отформатировать код, чтобы сделать его читаемым в комментарии.

Я задолбался, когда задавал вопрос выше.Извиняюсь.BoxCarIds в реальной программе не является глобальным.Программа выглядит так:

 function getBoxCarIds(){
     .  
     .
     .


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


 }

Длина массива BoxCarIds на самом деле уменьшается.Когда «грузовой поезд» довольно короткий, программа работает нормально.Ошибка возникает только тогда, когда поезд длинный (например, 140 вагонов).

...