Vue. js: Как загрузить шаблон асинхронно после извлечения данных из хранилища Firebase? - PullRequest
3 голосов
/ 22 января 2020

Итак, я пытаюсь получить ссылки на некоторые PDF-файлы из моего хранилища Firebase. Когда я получаю ссылку, я хочу связать их с определенными списками. Проблема в том, что шаблон загружается до получения ссылок, поэтому атрибут href списков остается пустым. Я тоже использую Vuetify.

Вот мой шаблон

<template>
  <v-layout row wrap v-if="count > 0">
    <v-flex v-for="n in count" :key="n">
      <v-card:href="link[n-1]" target="_blank">
        <v-icon>mdi-file-pdf</v-icon>
        <span>Module {{n}}</span>
      </v-card>
    </v-flex>
  </v-layout>

Вот мой script

<script>
import firebaseApp from "@/firebase/init.js";
var storage = firebaseApp.storage();
var storageRef = storage.ref();
export default {
  name: "Dashboard",

  data() {
    return {
      id: this.$route.params.id,
      count: null,
      link: [],
      loading: null
    };
  },

  methods: {
    getFile() {
      this.link = [];
      this.loading = true;
      var listRef = storageRef.child(`folder_name${this.id}`);

      listRef.listAll().then(res => {
        this.count = res.items.length;
        for (let i = 1; i <= this.count; i++) {
          var starsRef = storageRef.child(`folder_name${this.id}/file_name${i}.pdf`);
          starsRef.getDownloadURL().then(url => {
            this.link[i - 1] = url;
          });
        }
        this.loading = false;
      });
    },
    updateId() {
      this.id = this.$route.params.id;
      this.getFile();
    }
  },

  created() {
    this.getFile();
  },

  watch: {
    $route: "updateId"
  }
};
</script>

Массив ссылок со временем сохранит все ссылки. Но это не будет связано с тегом span. Как мне преодолеть это без использования vuex? Заранее спасибо

1 Ответ

1 голос
/ 22 января 2020

Метод getDownloadURL() является асинхронным и возвращает Обещание. Поскольку вы хотите выполнить этот метод параллельно для всех файлов в storageRef.child('folder_name${this.id}'), вы должны использовать Promise.all(), чтобы дождаться завершения всех асинхронных операций, прежде чем обновлять массив link.

Следующее, используя forEach() вместо for l oop, должно выполнить трюк (не проверено):

 listRef.listAll()
 .then(res => {
    const promises = [];
    res.items.forEach(itemRef => {    //items is an array of Reference
         promises.push(itemRef.getDownloadURL());
    });
    return Promise.all(promises);
 .then(urls => {
   this.link = urls;
 });

Тогда в вашем компоненте вы бы делать:

  <v-layout row wrap v-if="count > 0">
    <v-flex v-for="(item, index) in link">
      <v-card :href="item" target="_blank">
        <v-icon>mdi-file-pdf</v-icon>
        <span>Module {{index + 1}}</span>
      </v-card>
    </v-flex>
  </v-layout>
...