【问题标题】:fs.exists, fs.existsSync - why are they deprecated?fs.exists、fs.existsSync - 为什么不推荐使用它们?
【发布时间】:2015-04-16 10:56:30
【问题描述】:

我注意到官方节点文档对fs.exists 说了一些令人吃惊的事情:

"fs.exists() 是不合时宜的,仅出于历史原因而存在。 几乎不应该有理由在您自己的代码中使用它。

特别是,在打开文件之前检查文件是否存在 让你容易受到竞争条件影响的反模式:另一个 进程可能会在调用 fs.exists() 和 fs.open()。只需打开文件并在错误时处理错误 那里。”

我理解这个建议,打开一个文件,如果它不存在则处理错误,但我不明白为什么接口被弃用而不是实现简单地改变。

谁能向我解释为什么使用像fs.exists 一样简单和合乎逻辑的 API 来检查文件的存在是如此糟糕,以至于它应该被称为反模式并从节点 API 中删除?

【问题讨论】:

  • current implementation 基本上是这样的:function exists(file, cb){ fs.stat(file, function(err, stat){ cb(err); }); }。所以我不确定你所说的implementation simply changing 是什么意思。如果你真的必须知道一个文件是否存在,为什么不直接使用fs.stat?它做同样的事情,实际上会返回更多有用的信息。
  • @loganfsmyth - 他们可以在后台更改实现以进行更有效的检查,而无需生成错误并导致性能下降。使用 fs.stat() 会产生一个错误,这在访问许多文件时会显着影响性能。我个人更喜欢将 fs.exists*() 保留在 API 中,而只是重构实现。
  • 请参阅stackoverflow.com/questions/31799274/… 了解一些代码替代品,用什么代替fs.exists()

标签: node.js


【解决方案1】:

没有必要使用 fs.stat(),因为 fs.existsSync() 还没有被弃用。

https://nodejs.org/api/fs.html#fs_fs_existssync_path

fs.existsSync(path)

添加于:v0.1.21 路径 | fs.exists() 的同步版本。如果文件存在则返回 true,否则返回 false。

请注意,fs.exists() 已弃用,但 fs.existsSync() 不是。 (fs.exists() 的回调 >parameter 接受与其他 >Node.js 回调不一致的参数。fs.existsSync() 不使用回调。)

【讨论】:

【解决方案2】:

我认为是因为它是多余的。您可以通过尝试打开文件来检查文件是否存在。如果它不存在,它会给你ENOENT

> fs.open('foo', 'r', function(err, fd) {
    ... console.log(err, fd);
    ... 
})
undefined
> { [Error: ENOENT, open 'foo'] errno: 34, code: 'ENOENT', path: 'foo' } undefined

【讨论】:

  • 您可能想检查文件是否存在而不需要打开它!例如,如果你想阻止用户创建一个名称已经存在的文件,如果你想确保一个文件没有被外部删除等等。
  • @PhiLho 如果是这样,可以先使用statstatSync 来检查是否存在(见fs
  • 是的,就是上面所说的。只是说打开文件以查看它是否存在是矫枉过正的。当然,除非你真的想读它。
  • 我还可以补充一点,调用 exists() 比调用 open() 更“富有表现力”,在这种情况下,exists() 让我的意图更加明确。
  • if (fs.existsSync('somefile'))var exists = false; try { fs.statSync('somefile'); exists = true; } catch (e) { } if (exists) 之间存在很大差异。也就是说,后者超级烦人。 fs.existsSync 是一个很好的包装器。
【解决方案3】:

由于某些人认为它是一种反模式而被弃用。 IE。信任 exists() 然后对文件执行某些操作是不安全的,因为文件可以在 exists-call 和 doing-something-call 之间删除。

我同意上述情况。但对我来说,exists() 的用途更多。我将空的虚拟文件放在我的临时和缓存目录中。当我执行 dangerous 操作时,例如从缓存目录中删除旧文件,我会查找我的虚拟文件以确保我没有在错误的目录中操作。 IE。我只需要确认文件在那里。 Exists 非常适合这一点,但我想我会改用 stat()。

【讨论】:

    【解决方案4】:

    因为你引用的第二段。

    检查文件是否存在是没有意义的,因为它总是可以在检查后立即删除。

    【讨论】:

    • 这里有一点。我有一个要使用 API 上传的文件列表。我想在上传之前检查它们是否存在。现在我必须打开和关闭文件,这是额外的工作。我从一开始就不需要打开文件。
    • @MichaelCole:嗯?上传过程会打开文件。即使它在您调用上传之前就存在,也不能保证在您实际上传它时它会存在。这正是没有意义的地方。
    • 如果我想在写入文件之前检查目录是否存在怎么办?
    • @Petah:如果有人删除了这两行代码之间的目录怎么办?
    • @SLaks 与某些人在创建所述目录后尝试写入文件时删除目录没有什么不同。
    【解决方案5】:

    existsSync 的实现是这样的(v0.10.25):

    function (path) {
      try {
        nullCheck(path);
        binding.stat(pathModule._makeLong(path));
        return true;
      } catch (e) {
        return false;
      }
    }
    

    所以如果你写像if(fs.existsSync(thepath)){}这样的程序,最好改成if(fs.statSync(thepath)){}

    【讨论】:

    • 不一样。一个返回布尔值,另一个抛出错误!
    【解决方案6】:

    你可以使用新安装的这个并继续使用它:
    https://github.com/imyller/node-fs-exists-nodeback

    npm install fs-exists-nodeback
    

    【讨论】:

      【解决方案7】:

      我正在寻找此问题的解决方案,发现 fs.exists 和 fs.existsSync 已被弃用。这似乎在我的 senario 中运行良好

      fs.readFile(filename, 'utf8', function(err,data){
          // the err variable substitutes for the fs.exists callback function variable
          if (!err){
              // do what you planned with the file
              console.log(data)
          }else{
              // handle the non-existence of the file
              console.log('File does not exist!');
          }
      });
      

      【讨论】:

      • 根据docs,只有fs.exists已被弃用,而不是fs.existsSync
      猜你喜欢
      • 2016-03-02
      • 2014-01-21
      • 2017-10-10
      • 2016-02-23
      • 2017-11-04
      • 2011-10-22
      • 2011-04-11
      • 2021-10-12
      • 2012-12-07
      相关资源
      最近更新 更多