#firebase #firebase-realtime-database
#firebase #firebase-realtime-database
Вопрос:
В настоящее время я получаю неожиданное поведение от базы данных Firebase в реальном времени. Чтобы воспроизвести это, я использовал в точности приведенный ниже код, только используя Firebase JavaScript SDK ( 7.19.1
) с ванильным JS.
Код:
Остается неизменным для обеих версий.
Только правила безопасности будут изменены непосредственно в Firebase.
const CONFIG = { ... }; // TODO insert your config
const AUTH_TOKEN = "eyJ0..." // TODO insert your auth token (JWT)
firebase.initializeApp(CONFIG);
firebase
.auth()
.signInWithCustomToken(AUTH_TOKEN)
.then(() => {
console.log("authentication successful");
performFirebaseOperations();
})
.catch((error) => {
console.log("authentication failed", error);
});
const performFirebaseOperations = () => {
const database = firebase.database();
const allUsersRef = database.ref("users");
const myUserRef = database.ref("users/1");
allUsersRef.on("child_added", (data) => {
console.log("child_added", data.val());
});
allUsersRef.on("child_removed", (data) => {
console.log("child_removed", data.val());
});
myUserRef
.update({
name: "John",
})
.then(() => {
console.log("update success");
})
.catch((error) => {
console.log("update error", error);
});
};
Версия 1
Правила безопасности:
{
"rules": {
".write": false,
"users": {
".read": "auth !== null",
"$userId": {
".write": false,
}
}
}
}
Вывод на консоль:
Версия 2
Правила безопасности:
{
"rules": {
".write": false,
".read": false
}
}
В обеих версиях в базу данных Firebase никогда ничего не записывается, поскольку правила безопасности этого не позволяют.
В этой статье объясняется, что операции с базой данных Firebase в реальном времени оптимистичны, что объясняет, почему child_added
отображается в консоли, хотя оно никогда не записывалось в базу данных. Насколько я понимаю, версия 1 является ожидаемым поведением. Но почему версия 2 не показывает такое же поведение, хотя я только изменил правила безопасности? Я думал, что обновление является оптимистичным без предварительного обращения к серверу, поэтому я ожидал child_added
события.
Ответ №1:
Я думаю, что я понял это, но это другой крайний случай.
Я смог получить тот же результат с правилами, которые разрешают запись, переведя клиент в автономный режим перед любой другой операцией.
firebase.database().goOffline();
На этом этапе поведение с вашим первым набором правил такое же, как и со вторым набором правил.
Мой тестовый стенд, хотя вы не сможете изменить мои правила:https://jsbin.com/guzowak/edit?js ,консоль
Учитывая это…
Это сводится к гарантии того, что клиент Firebase никогда не покажет вам частичный снимок.
В вашем первом случае поток выглядит следующим образом:
-
Ваш клиент прослушивает
/users
(для обоихchild_added
илиchild_removed
, но для этого шага было бы достаточно любого из них), поэтому он получает снимок данных для всех пользователей. -
Затем вы выполняете запись в
/users/1
, которая представляет собой модификацию узла, который клиент уже знает, чтобы он мог запустить локальное событие для этого изменения.
Во втором случае клиент никогда не получает данные для /users
на шаге 1, поэтому он не может запустить событие на шаге 2.
Комментарии:
1. Это интересно. Я не получаю никаких выходных данных консоли, если раскомментирую
goOffline
часть. Я также пробовал это с моей версией, и моя консоль выводит только «аутентификация прошла успешно» и никаких других операций. Но я думаю, что это то, что вы имеете в виду? Что операция ничего не делает.2. Если я изменю
update
операцию наset
операцию с автономной версией, я получу тот же результат (толькоchild_added
событие). Думаю, теперь я это понимаю, потому что Firebase имеет локальную версию базы данных на стороне клиента, и в этой локальной версии путь для «пользователей» не существует, и поэтому он не может что-то здесь обновить, если я правильно понимаю.3. Да, это последнее утверждение действительно является сутью. И извините, что не понял, что
set()
это исправит, поскольку это действительно решает проблему. Отset()
клиент может гарантировать, что теперь это полное значение узла. Для такого небольшого API база данных в реальном времени имеет много нишевого поведения. 🙂