Reputation: 467
I'm new to web development and things like asynchronicity and promises aren't very clear to me yet so maybe this question might seem a little basic.
Basically I need to fetch the details of a "lesson". In the lesson details is a list of ids which will need to be fetched from another collection. As fire base doesn't support WHERE IN queries I am looping over the values one by one, running the query and appending the result to an array.
I have one query to fetch "lesson" details and another query to fetch a list of "words" by id, both of these queries are called sequentially from a third function and i've made them all synchronous because otherwise I get an error that word_ids (in getWordsById) is undefined (as it has no value until the promise from the query before resolves).
Is there a way to do this asyncronously so I don't have to chain synchronous queries ? I feel like I am missing some understanding of how promises work
async getWordsById(word_ids) {
var words = []
var arrayLength = word_ids.length;
for (var i = 0; i < arrayLength; i++) {
await this.db.collection('words_2').doc(word_ids[i])
.get().then(function(snap) {words.push(snap.data())})
}
//console.log("Words In Func: ", words)
return words
}
async getPractice (lessonId) {
var practice_details;
await this.db.collection('practice').doc(lessonId)
.get().then(snap => {practice_details = snap.data(); return practice_details;})
//console.log("Out: ", practice_details)
return practice_details;
}
async getThem (lessonId) {
var lesson_info = await this.getPractice(lessonId)
//console.log("Lesson info:", lesson_info.words_id.split(","))
var word_info = this.getWordsById(lesson_info.words_id.split(","))
//console.log("words ", word_info)
return word_info;
}
Upvotes: 1
Views: 58
Reputation: 1783
I will try to explain the concept with simple code block:
const func1 = (num, ms) => new Promise((res, rej) => {
console.log(`func1 for ${num}`);
setTimeout(() => { res(`func1 for ${num}`) }, ms);
});
const func2 = (resp, num, ms) => new Promise((res, rej) => {
console.log(`func2 for ${num}`);
setTimeout(() => { res(`${resp} func2 for ${num}`) }, ms);
});
async function x() {
await Promise.all([1, 2, 3, 4].map(async (num) => {
let resp1 = await func1(num, 5000);
let resp2 = await func2(resp1, num, 5000);
console.log(resp2);
}));
console.log('Done!!');
}
x();
Function x() is the main one, it iterates over array of numbers, which calls func1 asynchronously. Once func1 resolves, func2 is called using the response of func1, and then it takes its own sweet time to resolve. Hope it helps.
--- Probable code solution (couldn't test of course) ---
async function getWordsById(word_ids) {
var words = [];
await Promise.all(word_ids.map(async word_id => {
return new Promise((resolve, reject) => {
let resp = this.db.collection('words_2').doc(word_id).get();
words.push(resp.data());
resolve('');
});
}));
return words;
}
async function getPractice (lessonId) {
return new Promise((resolve, reject) => {
let resp = this.db.collection('practice').doc(lessonId).get();
resolve(resp.data());
});
}
async function getThem (lessonId) {
var lesson_info = await this.getPractice(lessonId)
var word_info = await this.getWordsById(lesson_info.words_id.split(","))
return word_info;
}
Upvotes: 1