Как сделать связанные запросы Firebase асинхронными - PullRequest
1 голос
/ 29 марта 2019

Я новичок в веб-разработке, и такие вещи, как асинхронность и обещания, мне пока не очень понятны, поэтому, возможно, этот вопрос может показаться немного базовым.

В основном мне нужно получить детали "урока".В подробностях урока приведен список идентификаторов, которые нужно будет извлечь из другой коллекции.Поскольку fire base не поддерживает запросы WHERE IN, я перебираю значения по одному, выполняю запрос и добавляю результат в массив.

У меня есть один запрос для извлечения деталей «урока» и другой запрос для извлечения списка «слов» по ​​идентификатору, оба эти запроса вызываются последовательно из третьей функции, и я сделал их все синхронными, потому чтов противном случае я получаю сообщение об ошибке, что word_ids (в ​​getWordsById) не определен (так как он не имеет значения, пока не будет выполнено обещание из запроса до).

Есть ли способ сделать это асинхронно, чтобы мне не приходилось чередовать синхронные запросы?Я чувствую, что мне не хватает понимания того, как работают обещания

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;
  }

1 Ответ

1 голос
/ 29 марта 2019

Я попытаюсь объяснить концепцию простым блоком кода:

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();

Функция x () является основной, она перебирает массив чисел, вызывающий func1 асинхронно. Как только func1 разрешается, вызывается func2 с использованием ответа func1, а затем для его разрешения требуется определенное время. Надеюсь, это поможет.

--- Возможное решение кода (конечно, не смог проверить) ---

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;
}
...