javascript 递归承诺?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21144707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 20:12:03  来源:igfitidea点击:

Recursive Promises?

javascriptangularjsasynchronouspromiseq

提问by Ivan Bacher

I would like to iterate over all files located in the HTML 5 file system and have some event get started once the iteration is complete. Since this is async + promises im having a hard time trying to grasp how it should work.

我想遍历 HTML 5 文件系统中的所有文件,并在迭代完成后启动一些事件。由于这是异步 + 承诺,我很难理解它应该如何工作。

I am using a angularJS and have created a service to encapsulate html 5 file system specific features.

我正在使用 angularJS 并创建了一个服务来封装 html 5 文件系统特定功能。

This is the recursive function:

这是递归函数:

function walkDirectory(path) {

    fileSystem.getFolderContents(path) //this is the services and it returns a promise containing all files in the current folder or directory
        .then(function(entries) {

            for (var i = 0; i < entries.length; i++) {

                if(entries[i].isFile) {
                    console.log("is File: " + entries[i].name);
                    //do something with file here
                } 
                else if (entries[i].isDirectory) {
                    console.log("is Dir: " + entries[i].name);
                    walkDirectory(entries[i].fullPath);
                }
            }
        });
};

ideally i would like to call the function like so, and have it return a promise which gets executed once all files have been traversed.

理想情况下,我想像这样调用该函数,并让它返回一个承诺,一旦遍历所有文件,该承诺就会执行。

walkDirectory("/").then( function() {
  console.log(done);
});

Any tips/ ideas how this can be achieved?

任何提示/想法如何实现?

an idea would be to have an array of promises and add a new promise to the array for every file/directory. My attempt:

一个想法是拥有一个承诺数组,并为每个文件/目录的数组添加一个新的承诺。我的尝试:

function walkDirectory(path) {

    var defer= $q.defer();
    var promises = [defer.promise];

    fileSystem.getFolderContents(path)
        .then(function(entries) {

            for (var i = 0; i < entries.length; i++) {

                if(entries[i].isFile) {
                    console.log("is File: " + entries[i].name);
                    //do something with file here
                    defer.resolve();
                    promises.push(defer.promise);
                } 
                else if (entries[i].isDirectory) {
                    console.log("is Dir: " + entries[i].name);
                    promises.push(walkDirectory(entries[i].fullPath));
                }
            }
        });

    return $q.all(promises);
};

walkDirectory("/").then(function() {
    console.log("done");
});

This doesn't seem to be working since done is never displayed in the console.

这似乎不起作用,因为 done 从未显示在控制台中。

采纳答案by SLaks

You're returning the array before you populate it.

您在填充数组之前返回数组。

Instead, you need to return $q.all(promises)within the then()callback, and return the outer promise:

相反,您需要$q.all(promises)then()回调中返回,并返回外部承诺:

return fileSystem.getFolderContents(path).then(function(entries) {
    return $q.all(entries.map(function(e) {
        if (e.isFile) {
            // Do something
            return null;  // Don't wait for anything
        } else {
            // Do something
            return walkDirectory(e.fullPath);
        }
    }));
});