2011-12-26 2 views
1

У меня есть код, который завершает отдельный набор операций в цепочке. Сам набор операций выполняется в цикле. Из-за характера системы, с которой я имею дело, наборы операций необходимо выполнять синхронно (т. Е. Следующий набор операций не может быть выполнен до завершения первого набора). Асинхронное выполнение может отбросить удаленный процессор (не в моем контроле) и привести к сбою кода. Прямо сейчас, единственным способом, которым я смог заставить это работать, является использование предупреждающих ящиков, что является действительно хромым, а не вариантом. Я пробовал:Выполнение набора работ в цикле только после завершения предыдущего набора

  • с помощью $ .ajax и установка асинхр ложной
  • используя функцию отключения
  • коробки Уведомления (используется в отчаянии)

Вот код - Любые мысли ?:

$('input:checked').each(function(index){       

    //get the item's location id 
    var currentInput = $(this).val(); 

    var copyUser = function(){$.get(urlCopyPrefix + currentInput + urlSuffix);} 
    var moveUser = function(){$.get(urlMovePrefix + moveLocation + urlSuffix);} 

    var cleanup = function(){ 

     var newSibling = $('#module-' + moveLocation); 
     newSibling.before('<li>New Line</li>'); 

     alert('done'); 
    } 

    /* --> THIS IS THE CODE IN QUESTION <-- */ 
    $.when(copyUser()).pipe(moveUser).then(cleanup); 

}); 

ответ

1

Я думаю, вы должны прекратить использование .each(), поскольку он работает все итерации сразу, и вы не хочу этого делать.

Вот один из способов сделать это, используя функцию завершения и локальную функцию:

function copyMove(moveLocation, urlCopyPrefix, urlMovePrefix, urlSuffix) 
    var checked = $('input:checked'); 
    var index = 0; 

    function next() { 
     if (index < checked.length) { 
      var currentInput = checked.eq(index++).val(); 
      $.get(urlCopyPrefix + currentInput + urlSuffix, function() { 
       $.get(urlMovePrefix + moveLocation + urlSuffix, function() { 
        $('#module-' + moveLocation).before('<li>New Line</li>'); 
        next(); 
       }); 
      }); 
     } 
    } 

    next(); 
} 

или, используя deferreds:

function copyMove(moveLocation, urlCopyPrefix, urlMovePrefix, urlSuffix) 
    var checked = $('input:checked'); 
    var index = 0; 

    function copyUser() { 
     var currentInput = checked.eq(index).val(); 
     return $.get(urlCopyPrefix + currentInput + urlSuffix); 
    } 
    function moveUser() { 
     return $.get(urlMovePrefix + moveLocation + urlSuffix); 
    } 
    function cleanup() { 
     ++index; 
     $('#module-' + moveLocation).before('<li>New Line</li>'); 
     next(); 
    } 

    function next() { 
     if (index < checked.length) { 
      $.when(copyUser()).pipe(moveUser).then(cleanup); 
     } 
    } 

    next(); 
} 

записку о ваших deferreds: Вы должны передавать ссылки функции , а не вызовы функций. Это означает, что вы передаете имя функции без парнеров.

+0

Я прошу отличаться. 'copyUser' &' moveUser' не откладываются. Когда они будут вызваны, они вернут Отсрочку. Единственный способ для 'when' /' then' работать, если вы вызываете функцию, и передать возвращенную Deferred в 'when' /' then'. –

+0

Кроме того, он абсолютно * должен * использовать метод 'pipe'. Если вы просто добавляете функции 'then', они не будут ждать друг друга. OP явно хочет, чтобы 'moveUser' возвращался, прежде чем он запускает' cleanup'. Единственный способ добиться этого - через «трубу». –

+1

OK, переключитесь на 'pipe()'. Документ jQuery на трубе бесполезен. – jfriend00

1

Вы должны вернуть объект jqXHR из ваших функций:

var copyUser = function(){ 
     return $.get(urlCopyPrefix + currentInput + urlSuffix); 
    }, 
    moveUser = function(){ 
     return $.get(urlMovePrefix + moveLocation + urlSuffix); 
    }; 

Тогда вы можете сделать:

$.when(copyUser()).pipe(moveUser).then(cleanup); 

Если вы хотите ждать каждого элемента в петле, чтобы быть до следующего запуска, используйте это:

var $items = $('input:checked'), 
    length = $items.length, 
    copyUser = function(currentInput) 
    { 
     return $.get(urlCopyPrefix + currentInput + urlSuffix); 
    }, 
    moveUser = function() 
    { 
     return $.get(urlMovePrefix + moveLocation + urlSuffix); 
    }, 
    cleanup = function() 
    { 
     $('#module-' + moveLocation).before('<li>New Line</li>'); 
    }; 

function processUser(i) 
{ 
    $.when(copyUser($items.eq(i).val())).pipe(moveUser).then(function() 
    { 
     cleanup(); 
     i < length && processUser(++i); 
    }); 
} 

processUser(0); 
+0

Но все равно все это не срабатывает для всех функций 'copyUser() как только цикл .each() будет запускаться до его завершения, не дожидаясь чего-нибудь? – jfriend00

+0

Да, будет. Я не понял, что OP думает, что цикл работает async. Обновит мой ответ через минуту. –

+0

Не эта строка '$ .when (copyUser ($ items.eq (i) .val())) .pipe (moveUser())' собирается вызывать 'copyUser()' и 'moveUser()' немедленно? и передать их возвращаемое значение методам '.when()' и '.pipe()'. Я не думаю, что это то, чего хочет OP. Он не будет переадресовывать вызовы ajax. – jfriend00

Смежные вопросы