Асинхронный доступ к массиву в Firebase

Вот мой код:

var userRef = new Firebase("https://awesome.firebaseio.com/users/");

var tokenRef = userRef.child(key+'/tokens');
tokenRef.once('value', function(snapshot){

  var userTokenSync = $firebase(tokenRef);
  var userTokens = userTokenSync.$asArray();


  console.log(userTokens);
  console.log(userTokens[0]);

  for(var i=0, len = userTokens.length; i < len; i++) {
     console.log(userTokens[i]);
  }
  console.log('done');
})

Этот код получает маркеры пользователя из firebase, и я просто хочу просмотреть массив токенов.

Вот что мне дает консоль:

enter image description here

Как вы можете видеть, я не могу получить доступ к массиву. У вас есть представление о том, как я могу это сделать?

Спасибо заранее.

Ответы

Ответ 1

Добро пожаловать в асинхронную загрузку 101.

  var userTokens = userTokenSync.$asArray();

  console.log(userTokens);
  console.log(userTokens[0]);

  for(var i=0, len = userTokens.length; i < len; i++) {
     console.log(userTokens[i]);
  }
  console.log('done');

Первая строка этих фрагментов запускает загрузку ваших данных из Firebase. Но загрузка может занять некоторое время. И поскольку браузер не хочет блокировать вещи, он продолжает выполнять script.

К моменту, когда браузер выполнит ваш console.log(userTokens);, данные, скорее всего, еще не загружены. Таким образом, он просто печатает объект на консоли в качестве заполнителя.

К моменту, когда он попадает в цикл for, данные могут или не могут быть загружены из Firebase.

В какой-то момент вы нажали стрелку рядом с зарегистрированным userTokens. К этому времени данные загрузились из Firebase, а на консоли отобразились последние данные.

Решение предоставляется AngularFire в виде обещания. AngularFire promises, чтобы в какой-то момент в будущем были данные для вас. Если у вас есть фрагмент кода, который должен выполняться только при загрузке данных, вы можете записать его следующим образом:

  var userTokens = userTokenSync.$asArray();

  console.log(userTokens);
  console.log(userTokens[0]);

  userTokens.$loaded(function(userTokens) {
    for(var i=0, len = userTokens.length; i < len; i++) {
      console.log(userTokens[i]);
    }
    console.log('done');
  });

  console.log('at last line, but not done yet');

Update

Обратите внимание, что приведенное выше является плохим примером использования $loaded. Поскольку $loaded будет срабатывать только один раз, он будет регистрировать только начальное содержимое массива. Если вы просто пытаетесь увидеть, когда/когда ваши данные загружены, идиоматический подход состоит в том, чтобы добавить userTokens в область:

$scope.userTokens = userTokens;

И добавьте это в свой просмотр /HTML:

<pre>{{ userTokens | json }}</pre>

AngularFire теперь будет контролировать, когда пользовательTokens будет загружен или изменен каким-либо образом, и сообщит, что AngularJS обновит представление, если это произойдет.

Также см. следующие:

Yup... мы часто задаем этот вопрос.