简体   繁体   English

fs.promises.writeFile 在完成写入文件之前解析

[英]fs.promises.writeFile resolves before it finishes writing the file

I am probably missing something obvious with this, but I have spent several days looking for solutions to this issue and have not found any.我可能遗漏了一些明显的东西,但我花了几天时间寻找这个问题的解决方案,但没有找到任何解决方案。

I have a function that takes in an object, turns it into a string, and then uses the node File System to save it.我有一个 function,它接受一个 object,将它变成一个字符串,然后使用节点文件系统来保存它。 It is supposed to wait for the file to finish writing before it returns, however, for whatever reason it does not.它应该等待文件在返回之前完成写入,但是,无论出于何种原因它没有。

Instead, the function begins writing the file and calls the .then () and continues before the file has been written.相反,function 开始写入文件并调用 .then .then ()并在文件写入之前继续。 The file does finish writing, but it only happens after the promise has already been resolved, and thus, after the function has already continued.该文件确实完成了写入,但它只发生在 promise 已经被解析之后,因此,在 function 已经继续之后。

I'm using node.js and it's native fs.promises api which is what a lot of similar questions suggest (although many of them are from when fs.promises was still experimental)我正在使用 node.js 并且它是原生的fs.promises api 这是许多类似问题的建议(尽管其中许多来自 fs.promises 仍处于试验阶段)

The code:代码:

const fs = require(`fs`);
const fsPromises = fs.promises;
const path = require (`path`);

var server = `test`;
const settings = {
  "name": "srvr.name",
  "serverId": "srvr.id",
  "ownerId": "srvr.ownerId",
  "prefix": "!",
  "roles":
  {
    "bot":
    {
      "id": "srvr.me.roles.highest.id",
      "name": "srvr.me.roles.highest.name"
    }
  }
};

saveSettings (server, settings);

Function: Function:

async function saveSettings (server, settings) {

  const newSettings = await JSON.stringify (settings, null, `\t`);

  await fsPromises.writeFile (path.join (__dirname, `${server}.json`), newSettings)
  .then (console.log (`File Saved`));

  await console.log (fs.readFileSync (path.join (__dirname, `${server}.json`)));

  return console.log (`Settings Saved`);
}

Expected Result:预期结果:

File Saved
{
  "name": "srvr.name",
  "serverId": "srvr.id",
  "ownerId": "srvr.ownerId",
  "prefix": "!",
  "roles":
  {
    "bot":
    {
      "id": "srvr.me.roles.highest.id",
      "name": "srvr.me.roles.highest.name"
    }
  }
}
Settings Saved

Actual Result:实际结果:

File Saved
<Buffer 7b 0a 09 22 6e 61 6d 65 22 3a 20 22 73 72 76 72 2e 6e 61 6d 65 22 2c 0a 09 22 73 65 72 76 65 72 49 64 22 3a 20 22 73 72 76 72 2e 69 64 22 2c 0a 09 22 ... 150 more bytes>
Settings Saved

As you can see, the file is still being written when the function attempts to read it.如您所见,当 function 尝试读取文件时,该文件仍在写入。

From my understanding, fs.promises.writeFile returns a promise that will be resolved when the file has finished writing, but it doesn't appear to be doing so.根据我的理解, fs.promises.writeFile 返回一个 promise 文件完成写入后将被解析,但它似乎并没有这样做。

I started using fs.writeFile, however discovered that it did not return a promise and therefore await would not work with it.我开始使用 fs.writeFile,但发现它没有返回 promise,因此 await 无法使用它。 I have also tried fs.writeFileSync, just in case that might have worked, but as expected, it did not.我也尝试过 fs.writeFileSync,以防万一它可能起作用,但正如预期的那样,它没有。

I do not know if the object is too large, and so the file takes too long to write, but as far as I can tell, that shouldn't be an issue, as the promise should not resolve until the file has been written, regardless of how long it takes.我不知道 object 是否太大,因此文件写入时间太长,但据我所知,这应该不是问题,因为 promise 应该在文件写入后才能解析,不管需要多长时间。

I know I am probably missing something very obvious here, whether I'm missing the way writeFile works, or am using the wrong function altogether, but I do not know what.我知道我可能在这里遗漏了一些非常明显的东西,无论是我遗漏了writeFile的工作方式,还是完全使用了错误的 function,但我不知道是什么。

In case it is useful, this function is for use in a Discord bot using Discord.js如果它有用,这个 function 用于使用 Discord.js 的 Discord 机器人

Thanks in advance提前致谢

await console.log (fs.readFileSync (path.join (__dirname, `${server}.json`)));

This isn't how you do this.这不是你这样做的方式。

You want to你想要

console.log(await fsPromises.readFileSync (path.join (__dirname, `${server}.json`)));

The promise is returned by fsPromises.readFileSync, not console.log.该承诺由 fsPromises.readFileSync 返回,而不是由 console.log 返回。

The answer was noted in the comments by user Phix, but for good measure, the issue isn't that the file was still being written, but that by default readFile returns a buffer , not a string.用户 Phix 在评论中指出了答案,但从好的方面来说,问题不在于文件仍在写入,而是默认情况下 readFile 返回一个buffer ,而不是一个字符串。 The solution is to pass the encoding option to readFile/readFileSync, which probably should be utf-8 .解决方案是将编码选项传递给 readFile/readFileSync,它可能应该是utf-8 For good measure, you should also include that encoding when you write the file.为了更好地衡量,您还应该在编写文件时包括该编码。

When writing(async) file is in progress, it tries to read(sync) the file.当正在写入(异步)文件时,它会尝试读取(同步)文件。 So in your case there is no need to write file async.因此,在您的情况下,无需异步编写文件。 Also you use await on sync function calls unnecessarily.您还不必要地使用await同步 function 调用。 I would write the function as below via using both sync write and read.我会通过使用同步写入和读取来编写如下 function。

function saveSettings (server, settings) {

  const newSettings = JSON.stringify (settings, null, `\t`);

  const settingsPath = path.join(__dirname, `${server}.json`);
  fs.writeFileSync(settingsPath, newSettings); // writes settings sync

  console.log(fs.readFileSync(settingsPath)); //read settings sync and print

  console.log (`Settings Saved`);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM