В этом руководстве будут рассмотрены типичные варианты использования, с которыми вы столкнетесь при написании конечных точек RESTful API для чтения и записи в экземпляр базы данных Firebase.

Особое внимание будет уделено красивому асинхронному коду, в котором используется функция async/await в Node.js (доступна в версии 7.6 и выше).

(Не стесняйтесь сладко улыбаться, когда вы машете на прощание, чтобы позвонить в ад 👋)

Предпосылки

Я предполагаю, что у вас уже есть приложение Node.js, настроенное с помощью Firebase Admin SDK. Если нет, то ознакомьтесь с официальным руководством по установке.

Запись данных

Прежде всего, давайте создадим пример POST конечной точки, которая будет сохранять слова в нашем экземпляре базы данных Firebase:

Это очень простая конечная точка, которая принимает значения userId и word, а затем сохраняет данное слово в коллекцию words. Достаточно просто.

Но что-то не так. Нам не хватает обработки ошибок! В приведенном выше примере мы возвращаем код состояния 201 (означающий, что ресурс был создан), даже если слово не было должным образом сохранено в нашем экземпляре базы данных Firebase.

Итак, давайте добавим обработку ошибок:

Теперь, когда конечная точка возвращает точные коды состояния, клиент может отображать соответствующее сообщение пользователю. Например, «Слово успешно сохранено». Или «Невозможно сохранить слово, нажмите здесь, чтобы повторить попытку».

Примечание: если какой-то синтаксис ES2015 + кажется вам незнакомым, ознакомьтесь с Руководством по ES2015 Babel.

Чтение данных

Хорошо, теперь, когда мы записали некоторые данные в нашу базу данных Firebase, давайте попробуем прочитать их.

Во-первых, давайте посмотрим, как выглядит GET конечная точка, используя исходный метод на основе обещаний:

Опять же, достаточно просто. Теперь сравним его с async/await версией того же кода:

Обратите внимание на ключевое слово async, добавленное перед параметрами функции (req, res), и ключевое слово await, которое теперь предшествует оператору db.ref().

Метод db.ref() возвращает обещание, что означает, что мы можем использовать ключевое слово await, чтобы «приостановить» выполнение скрипта. (Ключевое слово await может использоваться с любым обещанием).

Последний res.send() метод будет запущен только после выполнения db.ref() обещания.

Это все хорошо, но истинная красота async/await становится очевидной, когда вам нужно объединить несколько асинхронных запросов в цепочку.

Допустим, вам нужно было последовательно запустить ряд асинхронных функций:

Не очень. Это также известно как «пирамида гибели» (и мы еще даже не добавили обработчики ошибок).

Теперь взгляните на приведенный выше фрагмент, переписанный для использования async/await:

Нет больше пирамиды гибели! Более того, все операторы await можно заключить в один блок try/catch для обработки любых ошибок:

Параллельные запросы async / await

Как насчет случаев, когда вам нужно одновременно получить несколько записей из базы данных Firebase?

Легкий. Просто используйте метод Promise.all() для параллельного выполнения запросов к базе данных Firebase:

Еще кое-что

При создании конечной точки для возврата данных, полученных из экземпляра базы данных Firebase, будьте осторожны, чтобы просто не вернуть весь snapshot.val(). Это может вызвать проблемы с синтаксическим анализом JSON на клиенте.

Например, предположим, что у вашего клиента есть следующий код:

snapshot.val() , возвращаемый Firebase, может быть либо объектом JSON, либо null, если запись не существует. Если возвращается null, response.json() в приведенном выше фрагменте выдаст ошибку, поскольку пытается проанализировать тип, не являющийся объектом.

Чтобы защитить себя от этого, вы можете использовать Object.assign(), чтобы всегда возвращать объект клиенту:

Спасибо за прочтение!

Хотите увидеть реальный проект, созданный на основе Firebase и Node.js? Попробуйте Vocabify, конструктор словарного запаса, который поможет вам запоминать слова, с которыми вы сталкиваетесь.