jQuery 的延迟异步任务

Deferred Async Tasks with jQuery

我是 JavaScript 中延迟 类 的新手,我想实现一个循环遍历表单并逐个提交的函数。

看起来 Deferred 类 是实现此目的的方法。

我尝试遵循 this answer,但由于某种原因我的实施开始,等待 3 秒并完成。我希望它每 3 秒显示一个不同的表单名称,直到完成所有表单然后完成。

我做错了什么? JSFIDDLE

function syncAll() {
        
  var promises = [];
  var forms = [
    {'name':'form 1'},
    {'name':'form 2'},
    {'name':'form 3'}, 
    {'name':'form 4'}];

  $.each(forms, function (index, value) {
    var def = new $.Deferred();
    setTimeout(function () {
      $("#output").html("Syncing: " + value.name);
      def.resolve({ 'message': 'finito!' });
    }, 3000);
    promises.push(def);

  });

  return $.when.apply(undefined, promises).promise();
}
    
    
    $.when(syncAll()).done(function(response){
        $("#output").html(response.message);
    });
    /*
    syncAll().done(function (response) {
      $("#output").html(response.message);
    }));
    */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output">Start</div>

JSFiddle:https://jsfiddle.net/TrueBlueAussie/v6cgak1u/2/

这使用 promise = promise.then(functionReturningNextPromise) 模式:

function syncAll() {
    var promise = $.when();  // Start with a resolved promise.
    var forms = [
      {'name':'form 1'},
      {'name':'form 2'},
      {'name':'form 3'}, 
      {'name':'form 4'}];

    $.each(forms, function (index, value) {
        promise = promise.then(function(){
            var def = $.Deferred();
            setTimeout(function () {
                $("#output").html("Syncing: " + value.name);
                def.resolve({ 'message': 'finito!' });
            }, 3000);
            return def.promise();
        });
    });
    return promise;
}


$.when(syncAll()).done(function(response){
    $("#output").html(response.message);
});

这可以通过替换 setTimeout 并使用定时承诺方法来改进,该方法也链接在一起(仍然使用 setTimeout 实现)。

请注意 new 不需要 $.Deferred()

编辑 :

可以利用 javascript 和 jQuery 的特性使代码稍微更简洁:

function syncAll() {
    var forms = [
        {'name':'form 1'},
        {'name':'form 2'},
        {'name':'form 3'}, 
        {'name':'form 4'}
    ];
    return forms.reduce(function(promise, value) {
        return promise.then(function() {
            return $("#output").delay(1000).html("Syncing: " + value.name).promise();
        });
    }, $.when()).then(function() {
        return {'message': 'finito!'};
    });
}

syncAll().then(function(response) {
    $("#output").html(response.message);
});

这与上面的范例基本相同,但利用了: