javascript - 为什么 node.js `fs.existsSync` 在用 promise 包装时不能正常工作?

标签 javascript node.js asynchronous fs

我正在编写一个函数 createFile 来在目录中创建一个文件,除非它已经存在。我正在使用 Node.js native fs 包来执行所有文件操作。我想让我的函数异步,所以我将所有 fs 函数包装在 promises 中:

function writeFilePromise(writePath, textContent) {
    return new Promise((resolve, reject) => {
      fs.writeFile(writePath, textContent, (err) => {
        reject();
      });
      resolve();
    });
  }

  function mkDirPromise(dir) {
    return new Promise(((resolve, reject) => {
      fs.mkdir(path.join(constants.FILES_STORAGE_DIR, dir), (err) => {
        reject(err);
      });
      resolve();
    }));
  }

然后我还想在 promise 中包装 fs.existsSync 以完成我的功能,但包装它会导致偶尔出现不正确的行为,即,如果该文件的目录不存在并且我想要创建一个没有文件的目录将被创建为空。通过调试,我发现只有同步 fs.existsSync 才能始终。 这是功能代码:

function createFile(dir, fileName, httpMethod, textContent) {
    return new Promise(((resolve, reject) => {
      const searchPath = path.join(ROOT_DIR, dir, fileName);
      if (httpMethod === POST && fs.existsSync(searchPath)) {
        reject();
      } else {
        const fileExistsStatus = fs.existsSync(path.join(ROOT_DIR, dir));
        (async function fsOperations() {
          try {
            if (!fileExistsStatus) {
              await mkDirPromise(dir);
            }
            await writeFilePromise(searchPath, textContent);
            resolve();
          } catch (err) {
            reject(err);
          }
        }());
      }
    }));
  }

我缺少什么以及如何将我的函数变成真正的异步函数?

最佳答案

occasional incorrect behavior, namely, if a directory for the file didn't exist and I wanted to create one the directory would be created empty without the file

这可能是由 writeFilePromise 尤其是 mkDirPromise 的不正确实现引起的。 fs.writeFilefs.mkdir 是异步的,但 promise 是同步解决的。应该是:

  function writeFilePromise(writePath, textContent) {
    return new Promise((resolve, reject) => {
      fs.writeFile(writePath, textContent, (err) => {
        if (err)
          reject(err);
        else
          resolve();
      });
    });
  }

  function mkDirPromise(dir) {
    return new Promise(((resolve, reject) => {
      fs.mkdir(path.join(constants.FILES_STORAGE_DIR, dir), (err) => {
        if (err)
          reject(err);
        else
          resolve();
      });
    }));
  }

这就是 util.promisify 的用途:

const writeFilePromise = util.promisify(fs.writeFile);

即便如此,这也是一个轮子的重新发明,因为已经有第三方包可以做到这一点甚至更多,即 fs-extra

createFile 的控制流很差,并且使用了 promise 构造反模式。因为它使用了async..await,所以它应该是:

async function createFile(dir, fileName, httpMethod, textContent) {
  const searchPath = path.join(ROOT_DIR, dir, fileName);
  if (httpMethod === POST && fs.existsSync(searchPath)) {
    throw new Error();
  } else {
    const fileExistsStatus = fs.existsSync(path.join(ROOT_DIR, dir));
    if (!fileExistsStatus) {
      await mkDirPromise(dir);
    }
    await writeFilePromise(searchPath, textContent);
  }
}

值得一提的是,existsSync 是稳定的 API 方法,可以用它来检查文件是否存在。作为the documentation州,

Note that fs.exists() is deprecated, but fs.existsSync() is not. (The callback parameter to fs.exists() accepts parameters that are inconsistent with other Node.js callbacks. fs.existsSync() does not use a callback.)

关于javascript - 为什么 node.js `fs.existsSync` 在用 promise 包装时不能正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50767829/

相关文章:

javascript - 成功回调响应数组长度未定义

ios - 如何在 Node JS 中使用 Amazon SNS 将 VoIP 推送通知发送到 iOS 设备

javascript - 如何通过循环更改 this.something 的值

javascript - 尝试在 Node 中运行同步 REST 请求时出现问题

JavaScript:在 Android 上阻止文本输入时的退格键

javascript - 如何创建受密码保护的网站?

swift 2 : UICollectionView - is it possible to return cell asynchronously?

javascript - 如何从异步调用返回响应?

javascript - 如果将两个单选按钮设置为 "Yes",我如何组合它们以显示相同的元素?

node.js - 在Azure Portal WebChat控制台中测试时如何查找机器人的conversationId?