【发布时间】:2019-08-27 12:35:42
【问题描述】:
我有一个小型开发网络服务器,用于将缺失的翻译写入文件。
app.post('/locales/add/:language/:namespace', async (req, res) => {
const { language, namespace } = req.params
// I'm using fs.promises
let current = await fs.readFile(`./locales/${language}/${namespace}.json`, 'utf8')
current = JSON.parse(current)
const newData = JSON.stringify({ ...req.body, ...current }, null, 2)
await fs.writeFile(`./locales/${language}/${namespace}.json`, newData)
})
显然,当我的 i18n 库像这样对一个文件进行多次写入时:
fetch('/locales/add/en/index', { body: `{"hello":"hello"}` })
fetch('/locales/add/en/index', { body: `{"bye":"bye"}` })
文件似乎被覆盖了,只保存了最后一次请求的结果。我不能只是附加到文件,因为它是 JSON。如何解决这个问题?
【问题讨论】:
-
您必须使用某种并发控制来保持两个同时尝试写入相同资源的并发请求不会相互干扰。
-
@jfriend00,但我该如何实现呢?我尝试创建一个对象,其中包含来自所有文件的数据,并且在每个请求而不是写入文件时,我首先将数据添加到该对象,然后写入对象的内容。但由于某种原因,这也不起作用。是的,正如我在评论中所写的那样,我正在使用 fs.promises
-
如果您有很多不同的文件要写入,并且可能有多个服务器写入,那么您几乎必须使用某种文件锁定,无论是操作系统提供的还是手动锁定文件并让后续请求等待文件锁定被清除。如果您只有在服务器上写入文件和可管理数量的文件,那么您可以创建一个文件队列来跟踪请求的顺序以及文件何时繁忙,并且它可以在特定时间返回一个承诺要求写作。
-
仅供参考,这就是数据库擅长的——管理并发。
-
您也可以考虑使用其他可以直接附加的文件格式(例如 CSV),尽管您仍然需要并发控制。
标签: javascript node.js fs