在 JS 中使用 Promise 链的正确方法
Posted
技术标签:
【中文标题】在 JS 中使用 Promise 链的正确方法【英文标题】:Proper way to use chain of promises with JS 【发布时间】: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 可以更简单吗?
【问题讨论】:
【参考方案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);
);
【讨论】:
以上是关于在 JS 中使用 Promise 链的正确方法的主要内容,如果未能解决你的问题,请参考以下文章