#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
коде; если что-то зависит от aPromise
, вы не сможете действовать синхронно, пока это не будет решено или отклонено (в любом случае, выполнено ). Не видя остальной части вашего кода, я не могу сказать , почемуupdateRoom
это должно быть или не должно бытьasync
, но рассмотрите это как вариант; это может быть достойным решением.2. Вы также подразумевали, что вы «перетираете» диск при каждом запросе, вместо того, чтобы часто обновлять объекты в памяти, а затем периодически сбрасывать память на диск (например, с
setInterval
помощью таймера, который сбрасывает ваш JSON). Почему вы записываете JSON на диск и почему так часто? Является ли это абсолютно необходимым, или это можно сделать другим способом, например, с помощью правильной базы данных или просто в конечном итоге согласованного дискового кэша?