Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Информация о файле JS: Обработка ошибок

Unix-философия гласит, что всё есть файл. То есть любое устройство, принтер, сканер и папка — это файлы. При этом нужно уметь различать типы этих файлов и проверять, чем они являются. Это нужно, чтобы была возможность работать с ними определенным образом.

Чтобы получить необходимую информацию о файле, Node.js в своем API дает для этого специальный объект — Stats. В этом уроке мы познакомимся с ним и узнаем, как с ним работать.

Информация о файле без Stats

Рассмотрим, как мы получаем информацию о файле сейчас. Мы извлекаем текущую ноду внутри и проверяем руками type:

// isFile(path)
const parts = getPathParts(path);
const current = this.tree.getDeepChild(parts);
return current && current.getMeta().type === 'file';

// isDirectory, isSocket, isSymbolicLink

Кроме type можно проверять что-нибудь другое.

Это нормальный рабочий подход, но тут всплывает сразу несколько неудобностей. Например, мы делаем проверку на основе строк, и если возникнет ошибка, мы не узнаем о ней. Допустим, кто-то ошибся в названии.

Также при более сложных проверках будет появляться дублирующая логика в разных местах. Поэтому здесь нужны функции, которые покажут, чем является файл, а также его дополнительные характеристики. Например, это функции isDirectory, isSocket, isSymbolicLink.

Информация о файле через Stats

Stats — это объект, в котором много разных параметров:

// util.inspect(stats)
{
  dev: 2114,
  ino: 48064969,
  mode: 33188,
  nlink: 1,
  uid: 85,
  gid: 100,
  size: 527,
  blocks: 8,
  atime: 'Mon, 10 Oct 2011 23:24:11 GMT',
  birthtime: 'Mon, 10 Oct 2011 23:24:11 GMT',
}

По ним можно узнать информацию о файле, например: когда и кем он был создан, сколько блоков занимает, кто его владелец.

Нам не понадобится такое количество параметров из примера выше. Достаточно знать, является ли что-то файлом или директорией. Но в дальнейшем это можно расширить до любой задачи, которая необходима при работе со статистикой.

Рассмотрим, как сделать правильный интерфейс. Его можно скопировать с Node.js API:

files.mkdirSync('/etc');
// У нас существует директория, поэтому gj'njve мы делаем на ней `statSync`,
// где указываем такой же параметр
files.statSync('/etc ').isDirectory(); // возвращается в объект, в котором есть много полезных методов
// Сокращенно можно написать:
files.isDirectory('/etc'); // true

Файловая система может иметь проверку isDirectory, но внутри она уже будет работать по-другому. Она будет вызывать statSync и проверять строчку files.statSync('/etc').isDirectory();.

Идентичная работа у Stats-объекта будет и с файлами:

// Создаем файл
files.touchSync('/file.txt');
// Извлекаем объект и проверяем isFile
files.statSync('/file.txt').isFile(); // true
files.isFile('/file.txt'); // true

Так как это единый интерфейс, он содержит те же функции и для папок, и для файлов, и для всего остального. Но, например, если мы вызовем isDirectory(), где работаем с файлом, то получим false, и наоборот. То есть мы зависим от того, с чем работаем.

Полиморфизм

Внутри интерфейса было бы удобнее разделять типы, потому что так проще обеспечить полиморфизм.

Например, в примере ниже видно, что в touchSync() при вызове addChild() мы создаем новый объект класса File:

// touchSync(path)
return parent.addChild(name, new File(name));
// file.getStats().isFile();

А в mkdirSync() мы создаем объект класса Dir:

// mkdirSync(path)
return parent.addChild(name, new Dir(name));
// file.getStats().isDirectory();

То есть в первом случае мы могли бы сразу создать Stats-объект и по-разному его конфигурировать. Но тогда придется делать это везде и постоянно. А в данных примерах мы инкапсулируем эту логику и зашиваем параметры в типы. Так этим управлять проще и удобнее, а код становится чище.

Получается, что file и dir – это отдельные объекты, которые придерживаются общего типа и имеют внутри метод getStats(). То есть когда мы создаем файл, у него есть getStats(), который возвращает объект статистики. И мы можем вызвать у него уже знакомые нам методы, например, isFile() или isDirectory().

В этом случае наш statSync() будет выглядеть так:

statSync(path) {
  const keys = getPathParts(path);
  const current = this.tree.getDeepChild(keys);
  return current.getMeta().getStats();
}

Здесь мы извлекаем нашу ноду и достаем из нее мета.

Нужно понимать, что мета – это еще не статистика. Это new File() или new Dir(), а у него мы дальше берем getStats(). Здесь и срабатывает полиморфизм подтипов.


Дополнительные материалы

  1. Stats в стандартной библиотеке Node.js

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»