не подталкивание элементов в инструкции forEach

0 Suluuboi [2018-03-05 12:15:00]

У меня есть объект:

enter image description here

Это функция, которую я использую для прокрутки объекта:

function getAllUsersKeys(user){

    var promise = new Promise((resolve, reject) => {
    var tokens = []

    user.forEach(function(user) {
            admin.database().ref('/FAVORITES/${user.key}').orderByKey().once('value').then((favShops) => {
            favShops.forEach((shop)=>{
                if(shop.key==saledata.store_id){    //if store that activated sale if found under users list under /FAVORITES

                    admin.database().ref('/FAVORITES/${user.key}/token').orderByKey().once('value').then((token) => {
                        //console.log(token.val().id);
                        tokens.push(token.val().id);                
                    })
                }
            })
        })
    })
    resolve(tokens);
    })

    return promise;
}

консольное сообщение распечатает "id" в выбранном токене.

//console.log(token.val().id);

но когда я нажимаю этот "id" в массив, называемый токенами, ничего не появляется.

tokens.push(token.val().id);

В основном то, что я хочу, чтобы этот метод выполнял, - это вернуть массив с выбранным количеством "id".

Пожалуйста, помогите мне оптимизировать мой код. Сейчас он возвращает пустой массив.

javascript firebase firebase-realtime-database


1 ответ


1 jens [2018-03-05 12:25:00]

Проблема в том, что вы разрешаете свое обещание getAllUserKeys до того, как обещания firebase будут решены. Причина, по которой ваш console.log работает, заключается в том, что он ждет, пока ваш поиск в firebase не будет выполнен до регистрации. Когда вы resolve(tokens), обещания, которые заполняют этот массив, еще не разрешены.

Вам нужно будет убедиться, что все ваши обещания в битве были решены до того, как вы решите resolve(tokens).

ОБНОВИТЬ:

Я не могу легко проверить это, поэтому, скорее всего, это не сработает.

function getAllUserKeys(user) {
  return Promise.all(user.map(user => {
    return admin.database().ref('/FAVORITES/${user.key}').orderByKey().once('value');
  })).then(favShops => {
    return Promise.all(favShops.filter(shop => {
      if(shop.key === saledata.store_id) { 
        return admin.database().ref('/FAVORITES/${user.key}/token').orderByKey().once('value');
      }
      return false;
    }))
  }).then(tokens => {
    return tokens.map(token.val().id);
  })
}

Это пример того, как вы будете связывать обещания.

  1. Преобразуйте массив пользователей и объедините обещания от firebase, это решит favShops.
  2. В then метод вы получите результат обещания всем, что должно быть массивом favShops.
  3. Возьмите favShops и отфильтруйте только те магазины, которые соответствуют saledata.store_id, возвращая обещания, которые будут решаться с помощью firebase api.
  4. Как только все отфильтрованные обещания магазинов разрешатся, вы возьмете массив токенов и преобразуете их в массив идентификаторов.
  5. Используйте getAllUserKeys().then(tokens => {}) где токены должны быть массивом идентификаторов.