【问题标题】:nodejs fs.exists() and fs.existsAsync() are deprecated, but why can I still use it with Node v4 and v6nodejs fs.exists() 和 fs.existsAsync() 已弃用,但为什么我仍然可以将它与 Node v4 和 v6 一起使用
【发布时间】:2017-04-10 01:20:20
【问题描述】:

我在这里阅读 Nodejs 文档 https://nodejs.org/api/fs.html#fs_fs_exists_path_callback

它说fs.exists()fs.existsAsync() 已弃用。

所以我的直觉是,如果我使用较新版本的 NodeJs,它会引发错误。

但是,同时使用 NodeJs v4.3.2 和 v6,我仍然看到 fs.exists() 工作。为什么会这样?这是否意味着如果我从 NodeJS v0.10.0 迁移我的系统,我不一定必须更新调用此类函数的依赖项,并且它是向后兼容的?

【问题讨论】:

    标签: node.js fs


    【解决方案1】:

    这意味着 node.js 开发背后的社区现在建议不要使用此功能,因为它存在问题,他们可能会在将来的某个时候将其删除以迫使人们停止使用它。

    所以我的直觉是,如果我使用的是较新版本的 NodeJs,它会抛出错误。

    他们还没有让它抛出错误。

    但是,同时使用 NodeJs v4.3.2 和 v6,我仍然看到 fs.exists() 工作。为什么会这样?

    而且,从你的问题的标题:

    但为什么我仍然可以将它与 Node v4 和 v6 一起使用?

    因为虽然他们现在建议不要使用它,但他们还没有删除它。

    这是否意味着如果我从 NodeJS v0.10.0 迁移我的系统,我不必更新调用此类函数的依赖项,并且它是向后兼容的?

    没有。 node.js 背后的社区告诉你,他们保留在任何未来版本中删除这两个功能的权利。

    底线:如果您希望与未来版本兼容,请立即停止使用 fs.exists()


    fs.exists() 也与其他 node.js 异步 API 不一致,因为回调没有遵循 fn(err, data) 的典型调用约定。它没有 err 参数,这使它成为一个奇怪的东西。

    您可能还想了解它们使用起来有问题的原因。现代操作系统是一个多任务系统,文件系统是潜在的许多进程之间的共享资源。这意味着如果你这样做:

    if (fs.existsSync("somefile")) {
        // execute some code when somefile does exist 
    } else {
        // execute some code when somefile does not exist
    }
    

    然后,somefile 是否存在的状态可能会在您运行fs.existsSync() 调用和执行假定它知道文件是否存在的代码之间发生变化。这被称为“竞争条件”,它被认为是非常糟糕的设计,因为它可能会产生极难重现的错误,这些错误可能只是偶尔发生(可能是最难找到的错误类型)。

    请直接从 fs.exists() 的 node.js 文档中注意这一点:

    在调用之前使用fs.exists()检查文件是否存在 不推荐使用fs.open()fs.readFile()fs.writeFile()。正在做 所以引入了竞争条件,因为其他进程可能会改变 两次调用之间的文件状态。相反,用户代码应该 直接打开/读取/写入文件并处理引发的错误,如果 文件不存在。

    如果您使用的是异步版本fs.exists(),那么竞争情况会更糟,因为您自己的 node.js 代码甚至可能会因为您的 if/else 逻辑运行而改变文件的状态。

    根据您通常尝试执行的操作,非竞争条件替代方法是尝试以某种独占访问权限打开文件。如果文件存在,您将成功打开它而没有竞争条件。如果该文件不存在,您只会收到一个错误,然后您可以处理该错误。在其他一些情况下,您只是尝试使用如果文件已经存在将失败的模式创建文件。这两种情况都在 OS 文件系统代码中使用原子比较,因此它们没有“竞争条件”。

    您现在应该修复您的代码。如果您仍然不明白建议的修复方法是什么,请发布您使用 fs.exists() 和周围代码上下文的代码,我们可以帮助您进行更好的设计。

    【讨论】:

    • @WABBIT0111 - 我很好奇你为什么选择你做的答案作为最佳答案,而它甚至没有尝试回答你问题标题中的问题?
    • 你是如何想出竞态条件解释的,我无法理解。弃用的原因是异步方法与 API 的其余部分不一致。
    • @PavelHoral - 对竞争条件的引用直接来自 node.js doc:: 在调用 fs 之前使用 fs.exists() 检查文件是否存在不推荐使用 .open()、fs.readFile() 或 fs.writeFile()。这样做会引入竞争条件,因为其他进程可能会在两次调用之间更改文件的状态。相反,用户代码应该直接打开/读取/写入文件并处理文件不存在时引发的错误。
    • @PavelHoral - fs.exists() 如何与 API 的其余部分不一致?
    • @PavelHoral - 他们仍然受制于比赛条件。如果您仍然要打开文件,最好只打开文件并在它不存在时处理错误(因为 node.js 文档非常清楚)。这不会受到竞争条件的影响。对于同步或异步版本都是如此。使用同步版本,您自己的进程不会有竞争条件,但其他进程仍然可以。我在答案中添加了对不一致异步回调的引用 - 不知道这一点。
    【解决方案2】:

    Node.js 中的稳定性级别 0(或已弃用)意味着它可以随时删除,但不一定在下一个版本中。

    不要依赖它们向后兼容,甚至不要依赖它们在不同版本之间具有相似的行为,即使它们存在。

    【讨论】:

      【解决方案3】:

      根据documentation

      稳定性:0 - 已弃用 此功能已知存在问题,并且已计划进行更改。不要依赖它。使用该功能可能会导致警告。不应期望向后兼容。

      换句话说,它可能会在任何时候退出或以其他方式完全停止工作,恕不另行通知。如果/当您迁移时,它可能会或可能不会起作用。

      就其价值而言,在其他软件的多个主要版本中保留已弃用的功能并不少见。在 OSS 世界中,我看到过在维护项目期间一直存在的弃用功能。大概是因为维护者/用户群对已弃用的功能有一些用处,因为它对于他们的用例来说已经足够好了(即使它不如它应该/可能的那么好,即使开发了更新的 API)。

      【讨论】:

        猜你喜欢
        • 2018-07-07
        • 1970-01-01
        • 2015-10-26
        • 2011-08-18
        • 2017-01-31
        • 2015-12-28
        • 2018-09-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多