从for循环内部返回promise

return a promise from inside a for loop

本文关键字:返回 promise 内部 循环 for      更新时间:2023-09-26

我有一个递归函数,我试图让它按顺序运行,每次都返回promise。该代码是递归的,运行良好,但仅适用于for循环中的第一项。

示例:

  • 文件夹:1-确定
  • 文件夹:11-确定
  • 文件夹:111-确定
  • 文件夹:111-确定
  • 文件夹:2-不正常
  • 文件夹:12-不正常
  • 所有异步下载按顺序完成

我想这是因为当我从内部返回promise时,for循环就会被中断。

function CopySubFolders(folder, destFolder) {
    // Recursively copy each subfolder
    return folder.getFoldersAsync()
    .then(function (folderlist) {
        if (folderlist.size > 0) {
            for (var i in folderlist) {
                var replace = Windows.Storage.CreationCollisionOption.replaceExisting;
                console.log("create folder: " + folderlist[i].name);
                return destFolder.createFolderAsync(folderlist[i].name, replace)
                .then(function (newdest) {
                   return CopySubFolders(folderlist[i], newdest);
                });
            }
        }
        else {
            return WinJS.Promise.as();
        }
    });
}

CopySubFolders(folder, self.localFolder)
.then(function () {
    completeFunc("Done");
    console.log("All asynchronous downloads completed in sequence.");
})

知道如何在不中断for循环的情况下返回promise吗?

附言:如果我使用forEach厕所,它不会被打断,但我失去了按顺序返回文件夹的能力。

示例:

  • 文件夹:1-确定
  • 所有异步下载按顺序完成
  • 文件夹:11-确定
  • 文件夹:111-确定
  • 文件夹:111-确定
  • 文件夹:2-确定
  • 文件夹:12-确定

是的,就像任何函数一样,如果执行return语句,函数将停止它正在执行的操作并返回。你应该能够完成你试图用以下东西做的事情:

编辑:如果您不需要它们按特定顺序完成,您可以使用WinJS.Promise.join()(在其他promise方言中也称为Promise.all())和map(我在这里分解内部以减少嵌套)来完成您想要做的事情:

function CopySubFolders(folder, destFolder) {
    return folder.getFoldersAsync()
    .then(function (folderlist) {
        return WinJS.Promise.join(folderlist.map(function (folder) {
            return CopyFolder(folder, destFolder);
        });
    });
}
function CopyFolder(folder, destFolder) {
    var replace = Windows.Storage.CreationCollisionOption.replaceExisting;
    console.log("create folder: " + folder.name);
    return destFolder.createFolderAsync(folder.name, replace)
           .then(function (newdest) {
                return CopySubFolders(folder, newdest);
           });
}

作为一个完整的旁注,请不要将for...in与数组一起使用。这是个坏主意。

作为这篇文章的一部分,如果需要的话,以下是如何按顺序创建文件夹(尽管不建议这样做):

function CopySubFolders(folder, destFolder) {
    var p = Promise.resolve();
    return folder.getFoldersAsync()
    .then(function (folderlist) {
        return folderlist.forEach(function (folder) {
            var replace = Windows.Storage.CreationCollisionOption.replaceExisting;
            console.log("create folder: " + folder.name);
            p = p.then(function () {    
                destFolder.createFolderAsync(folder.name, replace)
                .then(function (newdest) {
                    return CopySubFolders(folder, newdest);
                });
            });
        });
    });
    return p;
}

如图所示,另一种稍微干净一点的方法是使用folderlist.reduce():

function CopySubFolders(folder, destFolder) {
    return folder.getFoldersAsync()
    .then(function (folderlist) {
        return folderlist.reduce(function (sequence, folder) {
            var replace = Windows.Storage.CreationCollisionOption.replaceExisting;
            console.log("create folder: " + folder.name);
            return sequence.then(function () {    
                destFolder.createFolderAsync(folder.name, replace)
                .then(function (newdest) {
                    return CopySubFolders(folder, newdest);
                });
            });
        }, Promise.resolve());
    });
}