Каков наиболее эффективный способ записи часто меняющегося объекта JavaScript в файл в NodeJS? - PullRequest
1 голос
/ 08 июня 2019

У меня есть объект JavaScript с множеством различных свойств, и он может выглядеть примерно так:

var myObj = {
    prop1: "val1",
    prop2: [...],
    ...
}

Значения в этом объекте обновляются очень часто (несколько раз в секунду), и их могут быть тысячи. Новые значения могут быть добавлены, существующие могут быть изменены или удалены.

Я хочу иметь файл, в котором всегда есть обновленная версия этого объекта. Простой способ сделать это - просто записать весь объект в файл заново после каждого его изменения следующим образом:

fs.writeFileSync("file.json", JSON.stringify(myObj));

Это не очень эффективно для больших объектов, которые нужно писать очень часто. Есть ли лучший способ сделать это?

Ответы [ 2 ]

3 голосов
/ 08 июня 2019

Вы должны использовать базу данных. Что-то простое, например sqlite3, было бы хорошим вариантом. Иметь таблицу с двумя столбцами «Ключ» «Значение» и использовать ее в качестве хранилища значений ключей. Вы получите такие преимущества, как транзакции и лучшую производительность, чем файл, а также упростите ваш доступ.

1 голос
/ 08 июня 2019

Поддерживать файл (в файловой системе), содержащий текущее состояние быстро меняющегося объекта, на удивление сложно.В частности, настройка таким образом, чтобы какая-то другая программа могла прочитать файл в любое время, является сложной частью.Зачем?В любой момент файл может быть в процессе записи, поэтому читатель может получить противоречивые результаты.

Вот схема хорошего способа сделать это.

1) запишите файлреже, чем каждый раз, когда состояние меняется.Всякий раз, когда состояние меняется, звоните updateFile (myObj).Он устанавливает таймер, скажем, на 500 мс, а затем записывает самое последнее состояние в файл по истечении таймера.Примерно так: не отлажено:

    let latestObj
    let updateFileTimer = 0
    function updateFile (myObj) {
      latestObj = myObj
      if (updateFileTimer === 0) {
         updateFileTimer = setTimeout (
           function () {
             /* write latestObj to the file */
             updateFileTimer = 0
           }, 500)
      }
    }

Это записывает в файл последнее состояние вашего объекта, но не чаще, чем каждые 500 мс.

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

         updateFileTimer = setTimeout (
           function () {
             /* write latestObj to the file */
             fs.writeFile("file.json.tmp", 
                           JSON.stringify(myObj), 
                           function (err) {
                             if (err) throw err;  
                             fs.unlink ( "file.json", 
                                        function (err) {
                                          if (!err)
                                            fs.renameSync( "file.json.tmp", "file.json")
                                        } )
                           } )
             updateFileTimer = 0
           }, 500)

Есть еще одна вещь, о которой нужно беспокоиться.Между операциями unlink и renameSync существует короткий промежуток времени, когда файл "file.json" не существует в файловой системе.Итак, любая программа, которую вы пишете, которая ЧИТАЕТ "file.json", должна повторить попытку, если файл не найден.

Если вы используете Linux, MacOs, FreeBSD или другую производную от UNIX операционную систему для этого кода, он будет работать хорошо.Файловые системы этих операционных систем позволяют одной программе отсоединять файл, в то время как другая программа читает его.Если вы используете его в операционной системе, основанной на DOS, такой как Windows, операция отмены связи завершится неудачно, когда другая программа читает файл.

...