从for循环中返回一个promise [英] return a promise from inside a for loop

查看:198
本文介绍了从for循环中返回一个promise的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



示例:




  • 文件夹:1 - 确定

  • 文件夹:11 - 确定 / li>
  • 文件夹:111 - 确定

  • 文件夹:2 - 不成功 / li>
  • 所有异步下载按顺序完成。



我认为这是因为当我返回promise

 函数CopySubFolders(folder,destFolder){

()函数(文件夹列表){
if(folderlist.size> 0){
for(var i); //递归拷贝每个子文件夹
return folder.getFoldersAsync()
.then在文件夹列表中){
var replace = Windows.Storage.CreationCollisionOption.replaceExisting;
console.log(create folder:+ folderlist [i] .name);

返回destFolder.createFolderAsync(folderlist [i] .name,替换)
.then(function(newdest){
return CopySubFolders(folderlist [i],newdest);
});
}
}
else {
return WinJS.Promise.as();
}
});


$ b CopySubFolders(folder,self.localFolder)
.then(function(){
completeFunc(Done);
console.log(按顺序完成所有异步下载);
})

任何想法如何在不中断for循环的情况下返回promise?



如果我使用forEach厕所,它不会被打断,但是后来我放弃了



示例:


  • 文件夹:1 - 确定

  • 所有异步下载顺序完成。

  • 文件夹:11 - OK

  • 文件夹:111 -

  • 文件夹:111 - 确定

  • 文件夹:2 - 确定
  • li>

解决方案

是的,就像使用任何函数一样,如果执行 语句,函数将停止它正在做的事情并返回。你应该能够完成你想要做的事情:



编辑:如果你不需要它们来完成按照特定的顺序,你可以用 WinJS.Promise.join()(aka Promise.all() code>在其他承诺方言中)和 map (我将这里的内部分解为嵌套):

 函数CopySubFolders(folder,destFolder){
return folder.getFoldersAsync()
.then(function(folderlist){
返回WinJS.Promise.join(folderlist.map(函数(文件夹){
返回CopyFolder(文件夹,destFolder);
});
});
}

函数CopyFolder(folder,destFolder){
var replace = Windows.Storage.CreationCollisionOption.replaceExisting;
console.log(create folder:+ folder.name);

返回destFolder.createFolderAsync(folder.name,替换)
.then(function(newdest){
return CopySubFolders(folder,newdest);
});





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



作为这篇文章的一个痕迹,这里是如何你能够创建文件夹按顺序,如果你需要这是不建议的):
$ b $ pre $ 函数CopySubFolders(folder,destFolder){
var p = Promise.resolve() ;
$ b返回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 (函数(newdest){
return CopySubFolders(folder,newdest);
});
});
});
});

return p;





$ b

另一个稍微干净的方法来做同样的事情,如图所示这里是使用 folderlist.reduce()
$ $ $ $ $ p $函数CopySubFolders(文件夹,destFolder){
返回folder.getFoldersAsync()
.then(function(folderlist){
return folderlist.reduce(function(sequence,folder){
var replace = Windows.Storage.CreationCollisionOption.replaceExisting;
console.log(create folder (function());

return sequence.then(function(){
destFolder.createFolderAsync(folder.name,replace)
.then(function(newdest) {
return CopySubFolders(folder,newdest);
});
));
},Promise.resolve());
});
}


I have a recursive function and I am trying to make it run in sequence, returning the promise every time. The code is recursive and works well but works only for the first item in the for loop.

Example:

  • folder: 1 - OK
  • folder: 11 - OK
  • folder: 111 - OK
  • folder: 111 - OK
  • folder: 2 - NOT OK
  • folder: 12 - NOT OK
  • All asynchronous downloads completed in sequence.

I think it is because when I return the promise from inside, then the for loop gets interrupted.

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

Any idea how to return the promise without interrupting the for loop?

PS: if I use a forEach loo it will not get interrupted, but then I loose the capability of returning the folders in sequence.

Example:

  • folder: 1 - OK
  • All asynchronous downloads completed in sequence.
  • folder: 11 - OK
  • folder: 111 - OK
  • folder: 111 - OK
  • folder: 2 - OK
  • folder: 12 - OK

解决方案

Yes, just like with any function, if you execute a return statement, the function will stop what it's doing and return. You should be able to accomplish what you're trying to do with the following:

Edit: if you don't need them to complete in a specific sequence, you can accomplish what you are trying to do with WinJS.Promise.join() (a.k.a. Promise.all() in other promise dialects) and map (I'm factoring out the inner part here to cut down on the nesting):

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

As a complete side note, please don't use for...in with arrays. It's a bad idea.

And as a bit of a vestige of this post, here is how you would be able to create the folders in sequence if you needed to (though that is not recommended):

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

Another slightly cleaner way to do the same thing, as illustrated here, is to use 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());
    });
}

这篇关于从for循环中返回一个promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆