Создание собственной базы данных с использованием Node и FS - PullRequest
0 голосов
/ 08 сентября 2018

Итак, я пытаюсь создать базу данных, пару фрагментов функций, которые читают, пишут или создают файлы X.json. То, как я себе это представлял, - это папка БД, затем в этой папке куча папок с именами пользователей и там, куча файлов, таких как account.json, level.json и т. Д. Таким образом, каждая папка будет содержать пользователей данные, это код, который мне удалось написать до сих пор, и он работает. Но проблема в документах FS гласит, что использование fs.stat для проверки существования файла перед чтением / записью в него - плохая идея. Я не понимаю, почему, так как это кажется единственным способом сделать это, прежде чем я продолжу задавать вопросы, я хотел бы вставить свой код здесь:

socket.on('play', (data) => {
    fs.stat(`db/${data.username}/account.json`, (error, result) => {
      if(!error) {
        fs.readFile(`db/${data.username}/account.json`, (error, result) => {
          if(error) {
            throw error;
          } else {
            const rawResult = JSON.parse(result);

            if(data.password == rawResult.password) {
              socket.emit('playResponse', {
                success: true,
                msg: 'Login Succesfull'
              });
            } else {
              socket.emit('playResponse', {
                success: false,
                msg: 'Wrong Password!'
              });
            }
          }
        });
      } else if(error.code == 'ENOENT') {
        socket.emit('playResponse', {
          success: false,
          msg: 'Account not found'
        });
      }
    });
  });

Я не написал общую функцию, которая бы делала это для меня, потому что я понял, что приведенный выше код сейчас беспорядок. Итак, почему плохая практика проверять наличие файла (fs.stat) перед записью / чтением из них? Думаю, я мог бы что-то сделать с ошибкой, которую я получаю из функции readFile, и пропустить функцию fs.stat, но всякий раз, когда функция readFile встречает несуществующую папку, мой сервер просто падает.

Я не очень разбираюсь в Node, поэтому приведенный выше код, вероятно, является абсолютной чепухой. Вот почему я здесь!

Как я могу сделать так, чтобы мой сервер не падал, если readFile встречается с несуществующей папкой, а вместо этого просто генерирует «Account not Found» через socket.io? Если я добавлю этот код emit, мой сервер все равно выйдет из строя.

Я бы просто пошел с MongoDB или еще чем-нибудь, но у меня есть куча свободного времени, и делать такие вещи очень весело для меня. > Является ли использование БД, подобной монго, более безопасным, или люди делают это, чтобы им не пришлось тратить время на написание своей собственной БД?

Спасибо за вашу помощь!

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

Проблема в том, что файл можно удалить между тем временем, когда вы получили ответ на вызов stat и вызов readFile.

Рекомендованным способом является вызов readFile и проверка кода ошибки в обратном вызове readFile. Для версии на основе обратного вызова это будет выглядеть так:

socket.on('play', (data) => {
  fs.readFile(`db/${data.username}/account.json`, (error, result) => {
    if (error) {
      if (error.code === 'ENOENT') {
        socket.emit('playResponse', {
          success: false,
          msg: 'Account not found'
        })
      } else {
        // throw the error if you really want to exit the application for unknown errors
        throw error
      }
    } else {
      const rawResult = JSON.parse(result)

      if (data.password === rawResult.password) {
        socket.emit('playResponse', {
          success: true,
          msg: 'Login Succesfull'
        })
      } else {
        socket.emit('playResponse', {
          success: false,
          msg: 'Wrong Password!'
        })
      }
    }
  })
})
0 голосов
/ 08 сентября 2018

Но проблема в документах FS гласит, что использование fs.stat для проверки существования файла перед чтением / записью в него - плохая идея. Я не понимаю, почему

Причина указана в устаревших fs.exists документах:

Использование fs.exists () для проверки существования файла перед вызовом fs.open (), fs.readFile () или fs.writeFile () не рекомендуется. Это вводит условие гонки, поскольку другие процессы могут изменять состояние файла между двумя вызовами. Вместо этого пользовательский код должен открывать / читать / записывать файл напрямую и обрабатывать возникшую ошибку, если файл не существует.


Как я могу сделать так, чтобы мой сервер не падал, если readFile встречается с несуществующей папкой, а вместо этого просто выдает "Account not Found" через socket.io?

Вы неправильно обрабатываете ошибки. Например, вы вызываете ошибку в вашем обратном вызове .readFile, но ваш код оставляет ошибку необработанной, что приведет к «аварийному завершению» вашего приложения. Вы можете обернуть свой код блоком try/catch или использовать обещания. Обещания предоставляют хорошие API для обработки ошибок в вашем приложении. Node.js v10.0.0 представляет API-интерфейсы с обещаниями для fs API-модулей.

const fs = require('fs');
const fsPromises = fs.promises;
fsPromises.readFile(`db/${data.username}/account.json`).then(error => {
   // the file exists and readFile could read it successfully! 
   // you can throw an error and the next `catch` handle catches the error
}).catch(error => {
  // there was an error
});

Вы также можете использовать API с try/catch и await:

try {
  const content = await fsPromises.readFile(`db/${data.username}/account.json`);
  // the file exists and readFile could read it successfully!
} catch(error) {
 // handle the possible error
}

Если использование узла v10.0.0 не является опцией, вы можете использовать пакет npm, который предоставляет обернутые fs API, такие как fs-extra или draxt:

// using draxt
const $ = require('draxt');
const File = $.File;

const file = new File(`db/${data.username}/account.json`);
file.read('utf8').then(contents => {
   // the file exists and readFile could read it successfully!
}).catch(error => {
  // handle the possible error
});
...