【问题标题】:Asynchronus call inside recursive function递归函数内部的异步调用
【发布时间】:2013-12-07 06:17:03
【问题描述】:

我正在使用 CEF 在 javascript 中构建本机桌面应用程序,并且我有从 CEF 访问文件系统的 API。我有一个情景, 我需要在其中获取特定目录中所有文件的名称(可能有目录树)。我需要得到结果数组,我正在使用 jquery 承诺。我不明白的是:我什么时候解决获得最终结果数组的承诺?

/*read all directories under this and get path*/
    var result = [];
    function _processEntries(dirPath) {
        var dirEntry = new NativeFileSystem.DirectoryEntry(dirPath), deferred = new $.Deferred();

        /*async call*/
        dirEntry.createReader().readEntries(
            function (entries) {
                for (var i = 0; i < entries.length; i++) {
                    if (entries[i].isDirectory) {
                        _processEntries(entries[i].fullPath).done(function () {
                            deferred.resolve(result);
                        });
                    } else {
                        result.push(entries[i].fullPath);
                    }
                }
            },
            function (error) {
                console.log("Failed while reading dir:", error);
            }
        );
        return deferred.promise();
    }

//调用函数

_processEntries("C:/Users/abc").done(function(result){
    console.log("FILES ARRAY:",result);
});

如果我做错了,请建议任何其他技术:)

【问题讨论】:

  • 当您可以轻松使用更好的 Promise 库时,尽量不要使用 jQuery Promise。

标签: javascript promise jquery-deferred chromium-embedded


【解决方案1】:

我什么时候兑现承诺

异步调用结束后立即执行。否则,您将拥有deferred antipattern。避免这种情况,您可以在任何地方使用 Promise,并使用适当的组合。

此外,您不应在 _processEntries 函数之外初始化您的 result 变量 - 多次调用该函数会遇到很大问题。

function getDirectoryEntries(dirPath) {
    // a promise helper function
    var dirEntry = new NativeFileSystem.DirectoryEntry(dirPath),
        deferred = new $.Deferred();
    dirEntry.createReader().readEntries(deferred.resolve, deferred.reject);
    return deferred.promise();
}
function _processEntries(dirPath) {
    return getDirectoryEntries(dirPath).then(function (entries) {
        var promises = [];
        for (var i = 0; i < entries.length; i++) {
             if (entries[i].isDirectory) {
                  promises.push(_processEntries(entries[i].fullPath));
             } else {
                  promises.push($.when(entries[i].fullPath));
             }
        }
        return $.when.apply($, promises).then(function() {
             return [].concat.apply([], arguments);
        });
    });
}

这样称呼它:

_processEntries("C:/Users/abc").then(function(result){
    console.log("FILES ARRAY:",result);
}, function (error) {
    console.log("Failed while reading dir:", error);
});

【讨论】:

    【解决方案2】:

    嗯,我看到很少有错误,当第一个孩子返回时,你解决了整个承诺,你必须等待你的所有子目录完成相应的承诺,并且你解决了一个非内部的全局变量,看看这个例子的变化:

    function _processEntries(dirPath) {
        var result = [];
        var dirEntry = new NativeFileSystem.DirectoryEntry(dirPath), deferred = new $.Deferred();
    
        /*async call*/
        dirEntry.createReader().readEntries(
            function (entries) {
                var promises = [];
                for (var i = 0; i < entries.length; i++) {
                    if (entries[i].isDirectory) {
                        promises.push(_processEntries(entries[i].fullPath));
                    } else {
                        result.push(entries[i].fullPath);
                    }
                }
    
                if(promises.length === 0) {
                  deferred.resolve(result);
                } else {
                   $.when.apply($,promises).done(function() {
                    result.concat(arguments);
                    deferred.resolve(result);
                  })
                }
            },
            function (error) {
                console.log("Failed while reading dir:", error);
            }
        );
        return deferred.promise();
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-21
      • 1970-01-01
      • 2017-03-12
      • 2020-09-08
      • 2017-06-27
      • 1970-01-01
      • 2021-07-11
      • 2018-11-17
      • 2021-03-20
      相关资源
      最近更新 更多