【问题标题】:Proper way to use chain of promises with JS在 JS 中使用 Promise 链的正确方法
【发布时间】:2013-01-17 06:40:42
【问题描述】:

任务如下。我需要使用 fs2 库中的 rmdir 删除文件夹及其内容。它返回 deffered 承诺对象。完成后,我需要再次创建文件夹。并且函数也应该返回 promise 以进行进一步的链接。

我现在的代码是这样的:

function clearOutputDir() {
    var def = deferred();
    var def2 = deferred();

    if (fs.existsSync(outputFolder)) {
        def.resolve(fs2.rmdir(outputFolder, {recursive: true, force: true}));
    } else {
        def.resolve();
    }

    def2.resolve(def.promise.then(function () {
        return deferred.promisify(fs.mkdir)(outputFolder);
    }));

    return def2.promise;
}

看起来它有效,但它丑得要命。如果没有 def 和 def2 可以更简单吗?

【问题讨论】:

    标签: javascript node.js promise deferred fs


    【解决方案1】:

    首先,不需要自己创建未解决的承诺,使用 fs2 函数返回的承诺并“然后”处理它们会更干净,在这种情况下,Plynx 解决方案是一个很好的提示

    其次,由于事物的异步性质(以及文件系统函数内部的工作方式),您不应使用 fs.exists 函数,它通常已被弃用,最好不要使用它完全可以,但直接做你想做的事,并依赖最终的错误代码。 请参阅:https://groups.google.com/forum/?fromgroups=#!topic/nodejs/gRRuly79oRc 它更清楚地说明了这一点。

    解决方案: 除了承诺 fs.mkdir,您还可以使用 fs2 中的 mkdir,因为除非提供了自定义选项,否则它的工作方式与 fs.mkdir 完全相同(回退到),并且执行你想要,回报承诺。

    function clearOutputDir(outputFolder) {
        return fs2.rmdir(outputFolder, { recursive: true, force: true }).then(null, function (e) {
             // Ignore "No such dir" error, otherwise propagate further
             if (e.code === 'ENOENT') return null;
             throw e;
         }).then(fs2.mkdir.bind(fs2, outputFolder));
    }
    

    fs2.mkdir 只有在 fs2.rmdir 成功或 dir 不存在时才会运行。我已经使用 bind 将它与 outputFolder 一起传递,它的效果与:

    function clearOutuputDir(outputFolder) {
        ...
        }).then(function () { return fs2.mkdir(outputFolder); });
    }
    

    如果你决定使用 promisify,最好还是重用 promisified 版本,不要在每次函数调用时都创建它:

    var mkdir = deferred.promisify(fs.mkdir);
    function clearOutputDir(outputFolder) {
        ...
       }).then(function () { return mkdir(outputFolder); });
    }
    

    【讨论】:

    • 谢谢。我喜欢最初的方法。认为我理解的问题是 .then 返回承诺。有了它,一切都变得足够清晰了。
    【解决方案2】:

    考虑为此目的使用final-fs 库。看看它的链接示例 - 它非常干净。

    它使用when 库进行异步调用,因此几乎不可能陷入回调地狱。链接非常简单 - 通过在 resolve 函数中返回 Promise 来完成。

    代码如下所示:

    var ffs = require('final-fs');
    
    /**
     * @param {string} outputDir
     * @returns {Promise}
     */
    function clearOutputDir(outputDir) {
        return ffs.exists(outputDir)
            .then(function (exists) {
                if (exists) {
                    return ffs.rmdirRecursive(outputDir);
                }
            })
            .then(function () {
                return ffs.mkdir(outputDir);
            });
    }
    

    【讨论】:

      猜你喜欢
      • 2015-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 2013-04-23
      相关资源
      最近更新 更多