仅在上一组完成后才在循环中执行一组工作

时间:2011-12-26 22:06:45

标签: jquery synchronous jquery-chaining

我有一些代码可以在链中完成一组不同的操作。这组操作本身是在循环中执行的。由于我正在处理的系统的性质,操作集需要同步执行(即,在第一组完成之前,下一组操作不能执行)。异步执行可以抛弃远程处理器(不在我的控制之下),并导致代码失败。现在,我能够让这个工作的唯一方法是使用警报框,这是真正的跛脚,而不是一个选项。我试过了:

  • 使用$ .ajax,并将async设置为false
  • 使用睡眠功能
  • 警告框(用于绝望)

这是代码 - 任何想法?:

$('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);

});

2 个答案:

答案 0 :(得分: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();
}

或者,使用延迟:

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

关于延迟的说明:您必须传递函数引用,而不是函数调用。这意味着你传递函数名称没有parens。

答案 1 :(得分: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);