Несколько файлов fs.WriteFile на Node.js

#javascript #node.js #concurrency #writefile

Вопрос:

Прямо к делу, я запускаю http-сервер в Node.js управление информацией о регистрации заезда/отъезда в отеле, где я записываю все данные JSON из памяти в один и тот же файл с помощью «fs.WriteFile». Данные обычно не превышают максимум 145 КБ, однако, поскольку мне нужно записывать их каждый раз, когда я получаю обновление из своей базы данных, у меня есть потеря данных/плохой формат JSON, когда вызовы файла fs.WriteFile происходят один за другим сразу.

В настоящее время я решил эту проблему с помощью «fs.writeFileSync», однако я хотел бы услышать более сложное решение, а не использовать простое/плохое решение функции синхронизации. Использование fs.promises приводит к той же ошибке, так как мне снова приходится совершать несколько вызовов fs.promises. Согласно документации узла , многократный вызов fs.writefile или fs.promises небезопасен, и они предлагают использовать поток файлов, однако в настоящее время это не вариант.

Подводя итог, мне нужно дождаться нормального завершения файла fs.WriteFile, прежде чем пытаться выполнить какое-либо повторное действие записи, и использование обратного вызова бесполезно, так как я априори не знаю, когда необходимо выполнить действие записи. Заранее большое вам спасибо

Ответ №1:

Я предполагаю, что вы имеете в виду, что вы перезаписываете или усекаете файл, пока последний запрос на запись все еще записывается. На вашем месте я бы использовал API обещаний и прислушался к предупреждению из документации:

It is unsafe to use fsPromises.writeFile() multiple times on the same file without waiting for the promise to be settled.

Вы можете await привести к традиционному циклу или очень осторожно использовать .then() для «синхронизации» своих обратных вызовов, но если вы ничего больше не делаете в своем цикле событий, кроме чтения из базы данных и записи в этот файл, вы можете просто использовать writeFileSync это для упрощения/безопасности. Асинхронные API (обратный вызов и обещания) предназначены для того, чтобы позволить вашей программе делать другие вещи в то же время; если в этом нет необходимости, и асинхронные API усложняют ваш код, просто используйте синхронные API. Это верно для любого API узла или библиотечной функции, а не только fs.writeFile .

Существуют также библиотеки, которые будут выполнять операции с атомной файловой системой для вас и абстрагироваться от деталей реализации, но я думаю, что это, вероятно, излишне для вас, если вы не опишете свой вариант использования более подробно. Например, почему вы сбрасываете базу данных на диск в формате JSON так быстро/часто, как только можете, вместо того, чтобы хранить данные в памяти или использовать инкрементные обновления на основе событий (например, реальная локальная база данных с гарантиями атомарности и согласованности).

Комментарии:

1. Привет, ббурханс, спасибо за ваш ответ!

Ответ №2:

спасибо вам за ваш ответ! Поскольку мое приложение в основном является http-сервером,да, я занимаюсь другими вещами, а не просто вводом/выводом, хотя и с небольшим количеством запросов. Я еще раз рассмотрю решение promises, но в первый раз мне не повезло.

Чтобы объяснить больше, у меня есть: function updateRoom(data){ ...update things in memory... writetoDisk(); } и функция writeToDisk(){ fsWriteFile(….) }

Превращение функции writeToDisk в асинхронную функцию и реализация «ожидания» внутри нее по-прежнему не решает проблему, так как функция updateRoom вызовет диск записи, не дожидаясь его завершения. Подход «.затем» не может быть реализован, так как моя комната обновления вызывается постоянно и динамически .

Если вы случайно знаете 1-2 вещи об асинхронности-ждите, когда вы будете более чем рады объяснить мне немного больше, тем не менее, еще раз спасибо!

Комментарии:

1. Правильно: для создания writeToDisk() async function завещания требуется await его результат или что-то подобное, и это предназначено. Обещания, как правило , распространяются в async / await коде; если что-то зависит от a Promise , вы не сможете действовать синхронно, пока это не будет решено или отклонено (в любом случае, выполнено ). Не видя остальной части вашего кода, я не могу сказать , почему updateRoom это должно быть или не должно быть async , но рассмотрите это как вариант; это может быть достойным решением.

2. Вы также подразумевали, что вы «перетираете» диск при каждом запросе, вместо того, чтобы часто обновлять объекты в памяти, а затем периодически сбрасывать память на диск (например, с setInterval помощью таймера, который сбрасывает ваш JSON). Почему вы записываете JSON на диск и почему так часто? Является ли это абсолютно необходимым, или это можно сделать другим способом, например, с помощью правильной базы данных или просто в конечном итоге согласованного дискового кэша?