以编程方式创建jQuery承诺的链式序列

时间:2013-11-16 02:19:36

标签: jquery asynchronous promise jquery-deferred

我有一个函数通过在列表中的每个文件上调用单个deleteFile(filePath)来删除列表中的文件数组filePaths(我正在使用的某些APIS不支持批量删除)。函数deleteFile返回一个jQuery promise并在删除文件时解析/拒绝。

function deleteFiles(filePaths)
    var deferreds = $.map(fileKeys, function (val, index) {
        return deleteFile(filePath);
    });

    $.when.apply($, deferreds).then(function (schemas) {
        console.log("DONE", this, schemas);
        deferred.resolve();
    }, function (error) {
        console.log("My ajax failed");
        deferred.reject(error);
    });

我得到.reject调用列表中的一些文件(我知道它们存在),所以我想我可能需要将filePaths数组变成一个链接的调用,比如队列(b) / c这不是什么$。什么,是吗?它似乎立刻启动它们)。我知道如何做到这一点(如.deleteFile(path1).deletePath(path2)等等,当它们在这样的数组中时。

提前感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

$.when没有启动任何内容,它们是在您的地图循环中启动的。 $ .when只返回一个承诺数组的承诺。

如果您想按顺序使用它们,请使用reduce:

function deleteFiles(filePaths) {
    return filePaths.reduce(function(cur, next) {
         return cur.then(function() {
             return deleteFile(next);
         });
    }, $().promise());
}

如果你想按顺序使用它们,同时还要将数组返回各自的结果:

function deleteFiles(filePaths) {
    var ret = filePaths.slice(0);
    return filePaths.reduce(function(cur, next, i) {
         return cur.then(function() {
             return ret[i] = deleteFile(next);
         });
    }, $().promise()).then(function(){
         return $.when.apply($, ret);
    })
    //These don't make any sense to call in this function but sure
    .then(function(schemas) {
         console.log("DONE", this, schemas);
    }).fail(function(error) {
         console.log("My ajax failed");
    });
}

答案 1 :(得分:1)

  

这不是$。什么时候,是吗?似乎把它们全部发射出去了   一旦

新的更新回答: 我刚刚发现,对于新版本的jQuery(> 1.8),我们可以简单地使用$.then来链接jQuery promises。在您的情况下,您可以尝试:

function deleteFiles(filePaths){
    var d = jQuery.Deferred(), 
    for (var i=0;i<filePaths.length;i++){
        d.then(deleteFile(filePath[i]));
    }

    d.resolve();
}

您可以在jQuery Deferred and Promise for sequential execution of synchronous and asynchronous funcitons

查看我的类似答案

旧答案:

据我了解,你需要逐个处理返回的值,我认为你不需要关心执行回调的命令为 下一个deleteFile不依赖于前一个结果 。如果是这样的话,试试这个:

 function deleteFiles(filePaths){
        $.each(filePaths,function(index,val){
              deleteFile(val)
                .done(function(schema){

                })
                .fail(function(error){

                });
        });
   }

如果需要返回延迟,则另一种写入方式:

function deleteFiles(filePaths)
    return $.map(fileKeys, function (val,index) {
        return deleteFile(val);
    });
}

$.each(deleteFiles(yourfilePaths),function(index,val){
    val
    .done(function(schema){
    })
    .fail(function(error){
    });
});

如果你确实需要链接它们,我认为你可以创建一个这样的递归函数:

function deleteFiles(filePaths, currentIndex){
    if (filePath.length < currentIndex + 1){ //Stop condition.
        return;
    }

    var promise = deleteFile(filePath[currentIndex]);
    if (promise){
        promise
         .done(function(schema){
            //do your job with returned value, decide whether to call the next path in the chain
            deleteFiles(filePaths,currentIndex++);
         })
         .fail(function(error){
              //I assume that you don't call the next path if the current one returns error.
         });
    }
}