Чтение вложенных данных из Firebase возвращает что-то еще, кроме массива - PullRequest
0 голосов
/ 14 апреля 2019

Попытка прочитать (и ожидать) вложенный массив следующим образом:

var array = [
0: {subArrayy: {...}, title: "Title"}, 
1: {subArray]: {...}, title: "Title"},
...

Однако после чтения и (!) Вывода результат будет хорошим.Моя веб-консоль показывает массив, и все кажется хорошим.НО, выполнение array.length возвращает 0. И любая итерация возвращает неопределенное значение.

Я пытался использовать Ladosh _.toArray, что я видел ранее, но это абсолютно ничего не делает.

var locations = []; // Empty array

  var ref = db.ref("locations/");
  ref.once("value", function(snapshot) {

    snapshot.forEach(function(item) {
      var itemVal = item.val();
      locations.push(itemVal); // Adding new items seems to work at first

    });

  });
  console.log(locations, locations.length);

Вывод:

вывод хрома

Я ожидал, что это будет итеративно, так как я мог бы просто использовать массив 0 для навигации.

Ответы [ 3 ]

0 голосов
/ 14 апреля 2019

Firebase читает данные асинхронно, чтобы приложение не блокировалось во время ожидания сетевого трафика. Затем, когда данные загружены, он вызывает функцию обратного вызова.

Это легко увидеть, разместив несколько операторов журнала:

console.log("Before starting to load data");
ref.once("value", function(snapshot) {
  console.log("Got data");
});
console.log("After starting to load data");

Когда вы запускаете этот код, вывод:

Перед началом загрузки данных

После начала загрузки данных

Получил данные

Вероятно, это не тот порядок, который вы ожидали, но он точно объясняет, почему вы получаете массив нулевой длины при его регистрации. Но поскольку основной код продолжал работать сразу, к тому времени, когда вы console.log(locations, locations.length) данные еще не загрузили, и вы еще не отправили их в массив.


Решение состоит в том, чтобы гарантировать, что весь код, которому нужны данные из этих данных, либо находится внутри обратного вызова, либо вызывается оттуда.

Так что это будет работать:

var locations = []; // Empty array

var ref = db.ref("locations/");
ref.once("value", function(snapshot) {

  snapshot.forEach(function(item) {
    var itemVal = item.val();
    locations.push(itemVal);
  });

  console.log(locations, locations.length);

});

Как будет это:

function loadLocations(callback) {
  var locations = []; // Empty array

  var ref = db.ref("locations/");
  ref.once("value", function(snapshot) {
    snapshot.forEach(function(item) {
      var itemVal = item.val();
      locations.push(itemVal);
    });
    callback(locations);
  });
});

loadLocations(function(locations) {
  console.log(locations.length);
});

Более современный вариант этого последнего фрагмента - возвращать обещание, а не передавать обратный вызов.

function loadLocations() {
  return new Promise(function(resolve, reject) {
    var locations = []; // Empty array

    var ref = db.ref("locations/");
    ref.once("value", function(snapshot) {
      snapshot.forEach(function(item) {
        var itemVal = item.val();
        locations.push(itemVal);
      });
      resolve(locations);
    });
  })
});

И тогда вы можете назвать это так:

loadLocations().then(function(locations) {
  console.log(locations.length);
});

Или с современным JavaScript вы можете использовать async / await и делать:

let locations = await loadLocations()
console.log(locations.length);

Просто имейте в виду, что этот последний фрагмент все еще имеет то же асинхронное поведение, а среда выполнения JavaScript (или транспортер) просто скрывает его от вас.

0 голосов
/ 14 апреля 2019

Использование await для функций чтения также, кажется, помогает.

0 голосов
/ 14 апреля 2019

Установка функции сна на 300 мс, похоже, решает проблему. Я думаю, что это как-то связано с синхронизацией, хотя и не совсем уверен. Полагаю, что требуется лишь некоторое время для обработки запроса и назначения всего.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...