calling a function having callback in for loop

2019-03-06 23:14发布

问题:

I want to run window.resolveLocalFileSystemURI(file,success,fail) in for loop passing different file entries and want to return resolved entries in array only after I get all the entries.

function resolveFiles(result,callback)
{
    var resultData=[]
    window.resolveLocalFileSystemURI(result, function(entry)
    {
        resolvedGalleryImages.push(entry);

        callback(resolvedGalleryImages);
        resolvedGalleryImages=[];

    }, function(e)
    {
        alert("err"+e);}); 
    }

    //calling--
    //@filesarr has captured images uris
    for(i = 0; i < filesarr.length; i++)
    {
        resolveFiles(filesarr[i],function(result){
            var resultArr = result;
        });
    }

How can I prevent callback to be called before I get all the entries.

回答1:

There are multiple primary ways to attack a problem like this:

  1. Manual coding of an asynchronous loop
  2. Using promises to coordinate multiple async operations
  3. Using a library like Async to coordinate multiple async operations

Here's the manual version:

function getFiles(filesarr, doneCallback) {
    var results = new Array(filesarr.length);
    var errors = new Array(filesarr.length);
    var errorCnt = 0;
    var overallCnt = 0;

    function checkDone() {
        if (overallCnt === filesarr.length) {
            if (errorCount) {
                doneCallback(errors, results);
            } else {
                doneCallback(null, results);
            }
        }
    }

    for (var i = 0; i < filesarr.length; i++) {
        (function(index) {
            window.resolveLocalFileSystemURI(url, function (entry) {
                results[index] = entry;
                ++overallCnt;
                checkDone();
            }, function (e) {
                errors[index] = e;
                ++errorCount;
                ++overallCnt;
                checkDone();
            });
        })(i);
    }
}

getFiles(filesarr, function(errArray, results) {
    if (errArray) {
        // go errors here
    } else {
        // process results
    }
});

And, here's a version that uses ES6 promises:

// make a promisified function
function resolveFile(url) {
    return new Promise(function(resolve, reject) {
        window.resolveLocalFileSystemURI(url, resolve, reject);
    });
}

function getFiles(filesarr) {
    var promises = [];
    for (var i = 0; i < filesarr.length; i++) {
        promises.push(resolveFile(filesarr[i]));
    }
    return Promise.all(promises);
}

getFiles(filesarr).then(function(results) {
    // process results here
}, function(err) {
    // error here
});


回答2:

this is all based on all your functions being synchronous, and if not: be more specific what you're using. (there is no jQuery here yet your tags say jquery)

function resolveFile(path) {
    var result;
    window.resolveLocalFileSystemURI(path, function(file) {
        result = file;
    });
    return file;
}
var resolvedFiles = filesarr.map(resolveFile);
callback(resolvedFiles);