如何重新排序异步函数的执行?

时间:2013-09-07 18:55:46

标签: javascript asynchronous

if (option == 'Follow All') {
    for (var i = 0; i < userArray.length; i++) {
        followUser(params..);
    }

    // How to get this part to execute after followUser is done? (Basically when the for loop finishes)
    alert("There was a problem processing your request on Twitter to follow the following users: " + $('#errored-users').val());
    $('#errored-users').val('');
}

我怎样才能多次调用它并等待它完成?

var followUser = function(params..) {
    $.post('/api/1.0/followUser.php', {
        'user_to_follow': username,
        'username': user
    }).done(function(data) { {
            if (!is_batch) {
                alert("There was a problem processing your request on Twitter to follow @" + username);
            } else {
                //This currently gets executed last?
                var names = $('#errored-users').val();
                if (names == "") {
                    names = '@' + username + ', ';
                } else {
                    names += '@' + username + ', ';
                }
                $('#errored-users').val(names);
            }
};

4 个答案:

答案 0 :(得分:1)

由于您已经在使用jQuery,因此您可以轻松使用AJAX请求/承诺并等待所有这些完成。 $.when可以为您提供很多帮助:

var followUser = function(params..) {
    // return the promise!
    return $.post('/api/1.0/followUser.php', { ... });
};

if (option == 'Follow All') {
    var promises = [];
    for (var i = 0; i < userArray.length; i++) {
        promises.push(followUser(...));
    }

    $.when.apply(null, promises)
    .done(function() {
        // all users were successfully followed
    })
    .fail(function() {
        // at least one follow failed; no information about the others
        alert("There was a problem processing your request...");
        $('#errored-users').val('');
    });
}

所有请求完成后,这将调用.done处理程序,但只要一个失败,它就会调用.fail处理程序。

如果您希望在所有请求完成(成功或失败)之后运行某个处理程序,则需要手动执行此操作,例如:

var followUser = function(params..) {
    // return the promise!
    return $.post('/api/1.0/followUser.php', { ... });
};

if (option == 'Follow All') {
    var outcomes = { done: [], failed: [] };
    var total = userArray.length;
    function allFinished() {
         return outcomes.done.length + outcomes.failed.length == total;
    }

    for (var i = 0; i < total; i++) {
        followUser(...)
        .done(function() {
            outcomes.done.push(username);
        })
        .fail(function() {
            outcomes.failed.push(username);
        })
        // this must come last
        .always(function() {
            if (allFinished) {
                // outcomes contains the results
            }
        })
    }
}

这仍将使用jQuery的成功或失败请求的概念,这是基于Twitter的HTTP响应代码。如果您想自定义此行为,可以修改followUser

var followUser = function(params..) {
    return $.post('/api/1.0/followUser.php', { ... })
        .then(
        // first argument handles HTTP response successes, but you can
        // convert them to failures here:
        function(data) {
            if (convertSuccessToFailure) {
                return $.Deferred.reject(data);
            }
        });
};

答案 1 :(得分:0)

As of jQuery 1.5任何$.ajax family of functions返回a promise - 您可以将多个承诺合并到一个新承诺中,当使用$.when解决所有子承诺时,这个承诺将得到解决:

function followUser(/* params */) {
    return $.post('/api/1.0/followUser.php', {
            user_to_follow: username,
            username: user
        });
}

var userRequests = [];
for (var i = 0, l = userArray.length; i < l; i++) {
    userRequests.push(followUser(/* params */));
}
$.when.apply($, userRequests).then(function(data) { /* etc. */ });

答案 2 :(得分:0)

您可以定义一个全局变量,该变量包含对followUser的调用次数:

if(option =='Follow All'){     var countUsers = userArray.length;     for(var i = 0; i&lt; countUsers; i ++){         followUser(PARAMS ..);     } }

然后,如果完成所有用户,则将匿名函数更改为向后计数并执行最后一条语句:

function(data){     if(!is_batch){         alert(“在Twitter上处理您的请求以跟踪@”+用户名时出现问题);     } else {         (......)     }     countUsers--;     if(countUsers == 0){         alert(“在Twitter上处理您的请求以跟踪以下用户时出现问题:”+ $('#errored-users')。val());         $( '#出错用户')VAL( '')。     } };

答案 3 :(得分:0)

可能的解决方案是使用承诺(请参阅here进行深入说明)。它在Javascript中提供了一种新的编码方式,可以有效地使异步代码同步。 (这是对Promises的一个很大的简化 - see here用于解释它的文章。

您可以使用各种实现。我最常用的是:https://github.com/cujojs/when。其维基中提供的示例演示了承诺的力量(see here)。

使用when.js的代码的基本大纲将是这样的:

if (option == 'Follow All') {
  var deferreds = [];
  for (var i = 0; i < userArray.length; i++) {
      deferreds.push(followUser(params..));
  }

  when.all(deferreds).then(function everythingWasFine(suceededUsernames) {
    //do something with the responses e.g.
    alert(succeededUsernames.length + ' users were followed');
  },
  function somethingWentWrong(failedUsernames) {
    alert("There was a problem processing your request on Twitter to follow the following users: " + failedUsernames.join(','));
  });
}

var followUser = function(params..) {
  var defer = when.defer();
  $.post('/api/1.0/followUser.php', {
    'user_to_follow': username,
    'username': user
  }).done(function(data) {
        if (failure) {
           defer.reject(username);
        } else {
           defer.resolve(username);
        }
   });
   return when.promise;
 };