Рекурсивный Promise.all со снимком в Firebase
У меня есть следующая структура в моей базе данных Firebase:
Мне нужно получить значения ключей pin
, Для этого я работаю с рекурсивной функцией, подобной этой:
let pins = [];
const normalize = (snapchot) => {
snapchot.forEach(function(child) {
if(child.val().pin) {
pins.push(Promise.resolve(child.val().pin));
}
else normalize(child);
});
return Promise.all(pins);
}
А теперь позвони normalize
функция:
normalize(snapshot) // snapshot represents the data from the firebase db
.then(p => {
console.log(p); // [ 'mi-pin-agosto', 'mi-pin-julio' ]
})
.catch(err => {
// handle error
})
И это работает, но когда я отлаживаю этот код, я вижу, что return Promise.all(pins);
вызывается более одного раза. Мне нужно позвонить только один раз, после foreach
были полностью закончены; это с идеей для случая производительности, потому что snapshot
Данные больше, чем видно на изображении, которое я показываю.
Есть идеи???
1 ответ
Использовать только Promise.all
как только вы можете иметь рекурсивную функцию как функцию "внутри", нормализуйте
const normalize = (snapshot) => {
const process = x => {
let ret = [];
x.forEach(function(child) {
if(child.val().pin) {
ret.push(Promise.resolve(child.val().pin));
} else {
ret = ret.concat(process(child));
}
});
return ret;
});
return Promise.all(process(snapshot));
}
Этот код также не требует global
массив для хранения результатов
Тем не менее, как нет ничего asynchronous
о любом коде, который вы звоните - обойтись без обещаний внутри normalize
const normalize = (snapshot) => {
let ret = [];
snapshot.forEach(function(child) {
if(child.val().pin) {
ret.push(child.val().pin);
} else {
ret = ret.concat(normalize(child));
}
});
return ret;
};
Если вам действительно нужно использовать Promises для этого кода, вы можете просто
Promise.all(normalize(snapshot))
.then(p => {
console.log(p); // [ 'mi-pin-agosto', 'mi-pin-julio' ]
})
.catch(err => {
// handle error
})