Programmatically creating a chained sequence of jQuery promises

房东的猫 提交于 2019-11-30 10:51:30

$.when doesn't launch anything, they were launched in your map loop. $.when simply returns a promise for an array of promises.

If you want them sequentially, use reduce:

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

If you want them sequentially, while also getting the array back with respective results:

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");
    });
}
Khanh TO

this isn't what $.when does, does it? it seems to launch them all at once

New updated answer: I have just found out that for new versions of jQuery (>1.8), we can chain jQuery promises simply using $.then. In your case, you could try:

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

    d.resolve();
}

You could take a look at my similar answer at jQuery Deferred and Promise for sequential execution of synchronous and asynchronous funcitons

Old answer:

As I understand, you need to handle the returned value one-by-one, I think that you don't need to care about the orders of executing callbacks as the next deleteFile does not depend on the previous one's result. If that's the case, just try this:

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

                })
                .fail(function(error){

                });
        });
   }

Another way to write this if you need to return deferreds:

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

If you do need to chain them, I think you can create a recursive function like this:

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.
         });
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!