Ошибка Firebase.update: первый аргумент содержит undefined в свойстве
У меня есть простая функция Firebase, которая обновляет некоторые данные. Однако интерпретатор сообщает, что первый аргумент содержит "undefined" в свойстве 'users.tester1'. Можете, пожалуйста, помочь мне разобраться в этом?
Вот код функции:
var objify = function() {
var rv = {};
for (var i = 0; i < arguments.length; ++i)
rv[arguments[i]] = rv[arguments[i + 1]];
return rv;
}
addUser("tester1", []);
var addUser = function(name, edges){
if (!checkIfUsernameExists(name) && !checkIfNodeNameExists(name) && !checkIfEdgeNameExists(name)) {
var time = Firebase.ServerValue.TIMESTAMP;
// ЗДЕСЬ: Я думаю, что ошибка на этой строке
refs.users.update(objify(name, "filler"));
refs.users.child(name).set({
"id": time,
"edges": "filler"
});
refs.users.child(name).child("edges").update({
"to": "filler",
"from": "filler"
});
addNode(new Node(name, time, name));
for (var e in edges) {
refs.users.child(name).child("edges/to").update(objify(edges[e].name, true));
addEdge(new Edge(edges[e].name, time, edges[e].to, edges[e].arrows));
//TODO добавить "from" edge, чтобы знать, кто хочет вас съесть
}
refs.users.child(name).child("edges/to").set({"filler": null});
} else {
alert("имя пользователя/узла/ребра уже занято.");
}
};
Проблема в том, что когда я пытаюсь обновить refs.users
, интерпретатор говорит, что свойство 'users.tester1' имеет значение "undefined". Что может быть причиной этой ошибки и как я могу её исправить?
5 ответ(ов)
Когда вы передаете объект в Firebase, значения его свойств могут быть либо значением, либо null
(в этом случае свойство будет удалено). Однако они не могут быть undefined
, что, судя по ошибке, вы и передаете.
Попробуйте следующий фрагмент кода в изоляции, чтобы увидеть проблему:
var objify = function() {
var rv = {};
for (var i = 0; i < arguments.length; ++i)
rv[arguments[i]] = rv[arguments[i+1]];
return rv;
}
objify("name", "filler")
Результат будет следующим:
{name: undefined, filler: undefined}
Судя по всему, вы хотите передавать пары ключ/значение в функцию objify
в качестве чередующихся параметров. В этом случае вам нужно изменить функцию на следующую:
var objify = function() {
var rv = {};
for (var i = 0; i < arguments.length; i+=2)
rv[arguments[i]] = arguments[i+1];
return rv;
}
objify("name", "filler")
Теперь результат будет таким:
{name: "filler"}
Таким образом, ваша функция теперь правильно создает объект с нужными значениями.
Чтобы убедиться, что ваш объект не содержит неопределенных свойств, используйте этот простой трюк:
JSON.parse(JSON.stringify(ВашиДанныеJson));
Это позволяет создать глубокую копию вашего объекта, устраняя все неопределенные свойства.
Для получения дополнительной информации, посмотрите на этот кодPen: http://codepen.io/ajmueller/pen/gLaBLX
Ошибка, которую вы получаете, связана с тем, что библиотека Firebase не позволяет обновлять свойства с неопределенным значением (undefined). Однако, значения null допускаются и рассматриваются как "игнорируемые" при обновлении.
Ваша задача заключается в том, чтобы создать "сырой" трансформер, который будет игнорировать все методы и свойства прототипа, а также преобразовывать undefined в null или полностью удалять свойства с неопределенными значениями.
В вашем коде, ошибка, скорее всего, возникает на этой строке:
refs.users.update(objify(name, "filler"));
Убедитесь, что функция objify
корректно обрабатывает значения, передаваемые в нее, и не возвращает свойства с undefined. В текущем варианте, если objify
возвращает объект, содержащий свойства с неопределенными значениями, вызов update
вызовет ошибку.
Вот, как можно улучшить трансформер для удаления свойств с undefined значениями:
function cleanObject(obj) {
return Object.entries(obj)
.reduce((acc, [key, value]) => {
if (value !== undefined) {
acc[key] = value === null ? null : value; // сохраняем null как есть
}
return acc;
}, {});
}
Замените вызовы, где вы используете objify
, на:
refs.users.update(cleanObject(objify(name, "filler")));
И в других местах, например:
refs.users.child(name).set(cleanObject({
"id": time || null,
"edges": "filler" || null
}));
refs.users.child(name).child("edges").update(cleanObject({
"to": "filler" || null,
"from": "filler" || null
}));
Таким образом, вы избавитесь от ошибок связанных с обновлением значений, равных undefined.
Как было сказано выше, чтобы значения undefined
сохранялись как пустые значения в Firebase, вам нужно заменить их на null
.
Я использую следующий подход для исправления всех вложенных значений:
// Функция для поиска и замены
const replaceAll = (s = "", f = "", r = "") =>
s.replace(new RegExp(f.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), r);
// Для сохранения данных в Firebase
firebase.database().ref(`path`).update(
JSON.parse(replaceAll(JSON.stringify(val), "undefined", "null"))
);
Этот код сначала преобразует объект в строку JSON, заменяет все вхождения undefined
на null
, а затем парсит строку обратно в объект и обновляет данные в Firebase.
Чтобы получить значение uid
из объекта firstPaymentsData
, вы можете использовать метод Object.keys()
, как указано в вашем примере:
var key1 = Object.keys(firstPaymentsData)[0], // Получаем первый ключ из первого уровня
key2 = Object.keys(firstPaymentsData[key1])[0], // Получаем первый ключ из второго уровня
uid = firstPaymentsData[key1][key2].uid; // Получаем значение uid
Данный код извлекает первый ключ из объекта firstPaymentsData
, затем извлекает первый ключ из вложенного объекта и, наконец, получает значение uid
. Убедитесь, что структура вашего объекта соответствует ожиданиям, иначе могут возникнуть ошибки.
Как связать каждого пользователя с его данными в Firebase?
Как выполнить операцию SQL "LIKE" в Firebase?
Где найти документацию по форматированию даты в JavaScript?
Как проверить, содержит ли массив строку в TypeScript?
Ссылка и выполнение внешнего JavaScript-файла, размещенного на GitHub