在 $.each 方法之后调用函数

Call function after $.each method

我在数组上使用 $.each 方法将文件保存到本地文件夹。一旦 .each 方法完成数组中的最后一个文件,我如何执行一个函数? .done 方法无效。

 function downloadStartData() {
        $.each(startUpimageFilesArray,
            function (index, entry) {
                saveTofolder(entry.addy, entry.nameOfFile)
            });       
 };
 function saveTofolder(url, fileName) {
        try {
             WinJS.xhr({
                url: url,
                responseType: "blob",
             }).done(
                function writeBlobToFile(result) {
                var blob=result.response;
                var lFolder = Windows.Storage.ApplicationData; 
                var storeOption = Windows.Storage.CreateCollisionOption;
                lFolder.current.localFolder.createFileAsync(fileName, storeOption.replaceExisting
             ).then(function(file) {
               file.openAsync(Windows.Storage.FileAccessMode.readWrite
              ).then(function(output) {
                  var input = blob.msDetachStream();
                  Windows.Storage.Streams.RandomAccessStream.copyAsync(input, output
               ).then(function () output.flushAsync(
                ).then(function () {
                   input.close();
                       output.close();
                  )};
               )};
             )};
          )};
        )};
  }
catch (e) {
    WinJS.log && WinJS.log("Exception while using XMLHttpRequest object 
    " + e, "sample", "error");
        }
};

each是同步的。

您在 saveToFolder 中有异步代码。您可以将回调传递给 saveToFolder,然后在当前迭代完成后调用。

function downloadStartData() {
    var len = startUpimageFilesArray.length;
    function callback() {
        len--;
        if(len==0) {
            // Write your "done" code here!
        }
    }
       $.each(startUpimageFilesArray,
           function (index, entry) {
               saveTofolder(entry.addy, entry.nameOfFile, callback)
           });       
};

// ... 
                ).then(function () {
                  input.close();
                      output.close();
                      callback(); 
                 )};
// ...

你最内在的 then 函数在 saveToFolderdone 可以做到。您只需要确认在所有保存完成后调用您的函数。所以你可以通过另一个函数来表示当前完成的保存是否是最后一次,如果是,则执行你的功能。

这是一个如何操作的例子:

// add a new parameter "fnCompleted" to your saveTofolder
function saveTofolder(url, fileName, fnCompleted){ 
    // some other operation omited
    // below is the most inner then
    .then(function () {
         input.close();
         output.close();
         fnCompleted();
    });
}

function downloadStartData() {
    var allFilesCount = startUpimageFilesArray.length, completed = 0;
    function checkIfCompleted(){
        completed++;

        // if this is the last one, do the work
        if(completed >= allFilesCount){
            // do something
        }
    }

    $.each(startUpimageFilesArray,
        function (index, entry) {
            saveTofolder(entry.addy, entry.nameOfFile, checkIfCompleted)
    });
 };

调用代码必须以某种方式等待 saveToFolder 完成。您可以 return 承诺:

function saveTofolder(url, fileName) {
        var deferred = $.Deferred();
        try {
             WinJS.xhr({
                url: url,
                responseType: "blob",
             }).done(
                function writeBlobToFile(result) {
                var blob=result.response;
                var lFolder = Windows.Storage.ApplicationData; 
                var storeOption = Windows.Storage.CreateCollisionOption;
                lFolder.current.localFolder.createFileAsync(fileName, storeOption.replaceExisting
             ).then(function(file) {
               file.openAsync(Windows.Storage.FileAccessMode.readWrite
              ).then(function(output) {
                  var input = blob.msDetachStream();
                  Windows.Storage.Streams.RandomAccessStream.copyAsync(input, output
               ).then(function () output.flushAsync(
                ).then(function () {
                   input.close();
                       output.close();
                   deferred.resolve();
                  )};
               )};
             )};
          )};
        )};
  }
catch (e) {
    WinJS.log && WinJS.log("Exception while using XMLHttpRequest object 
    " + e, "sample", "error");
    deferred.fail();
        }
    return deferred.Promise();
};

现在,您可以使用 jquery.map 创建一个包含 return 承诺的数组,而不是 jquery.each

function downloadStartData() {
        var promises = $.map(startUpimageFilesArray,
            function (entry, index) {
                return saveTofolder(entry.addy, entry.nameOfFile)
            }); 
        return $.when(promises); // Returns a new promise that waits for all of them to complete   
 };