Typescript 阵列推入离子3不工作

Typescript 阵列推入离子3不工作,typescript,firebase,ionic-framework,ionic3,Typescript,Firebase,Ionic Framework,Ionic3,我正在用ionic 3和firebase构建一个应用程序。基本上,我希望能够拍摄多张照片,将其上传到firebase存储,然后获取指向这些照片的链接,并将这些链接放在firestore的文档中。但是,我在包含下载URL的数组中遇到了奇怪的行为。如果我运行该函数一次,它会将一个文档上传到firestore,但带有下载链接的数组是空的。如果我再次运行该函数,就会显示链接。这是我的密码: 变量: export class AboutPage { public photos: any; pub

我正在用ionic 3和firebase构建一个应用程序。基本上,我希望能够拍摄多张照片,将其上传到firebase存储,然后获取指向这些照片的链接,并将这些链接放在firestore的文档中。但是,我在包含下载URL的数组中遇到了奇怪的行为。如果我运行该函数一次,它会将一个文档上传到firestore,但带有下载链接的数组是空的。如果我再次运行该函数,就会显示链接。这是我的密码:

变量:

export class AboutPage {

  public photos: any;
  public downloadURLs: any;
  public link: string;
  public base64Image: string;

ngOnInit() {
    this.photos = [];
    this.downloadURLs = [];
  }
功能:

// Note: The uploading of the images works completely fine

  uploadForm() {
    //var testArray = [];
    var kuerzel = "teacher";
    var lehrerKuerzel = kuerzel.toUpperCase();
    var date = Date();
    var length = this.photos.length;
    var i = 0;
    while(i < length){
      const ref = firebase.storage().ref(`pruefungen/${lehrerKuerzel}/${date}/${i}`);
      ref.putString(this.photos[i], 'data_url').then((snapshot) => {
        this.downloadURLs.push(snapshot.downloadURL);
      });
      if(i + 1 == length)
      {
        var db = firebase.firestore().collection(`${lehrerKuerzel}`);
        db.add({
          TestName: pruefungsName,
          Klasse: klasse,
          Abteilung: abteilung,
          Datum: date,
          DownloadURLs: this.downloadURLs,
          Length: length,
          I: i
        });
      }
      i += 1;
    }

  }
我所尝试的:

使用本地数组

放入db.add{};在.then中,虽然数组总是完全显示,但包含i的if语句总是true,因为某种原因,i总是==length。因此,收藏中的物品总是太多

将承诺数组与Promise.all一起使用:

上载函数res.putString异步工作,这意味着您的while循环在文件实际上载之前运行到完成,因此在添加记录时,this.downloadURLs===[]只会在稍后填充,因为照片会逐个完成

在添加记录之前,您应该等待所有上传完成,因此您已经有了所有下载URL要在db上写入

一种方法是使用Observable ForkJoin,如中所述:

如果你熟悉承诺,这与承诺非常相似。forkJoin操作符允许我们获取一个可观察的列表并并行执行它们。一旦列表中的每个可观测值发出一个值,forkJoin就会发出一个可观测值,其中包含列表中所有可观测值的解析列表

这篇文章为您提供了处理此类需求的各种示例

在您的特定情况下,我建议您在循环中进行存储调用数组,然后使用ForkJoin等待结果,然后进行记录,如下所示:

// extra import you'll need
import { forkJoin } from "rxjs/observable/forkJoin";

var kuerzel = "teacher";
var lehrerKuerzel = kuerzel.toUpperCase();
var date = Date();
var upload = this.photos.map(i => {
    const ref = firebase.storage().ref(`pruefungen/${lehrerKuerzel}/${date}/${i}`);
    return ref.putString(i, 'data_url');
});
forkJoin(upload).subscribe(results => {
    // results is an array of snapshots
    var db = firebase.firestore().collection(`${lehrerKuerzel}`);
    db.add({
        TestName: pruefungsName,
        Klasse: klasse,
        Abteilung: abteilung,
        Datum: date,
        DownloadURLs: results.map(i => i.downloadURL),
        Length: this.photos.length,
        I: this.photos.length - 1
    });
});

我还没有测试过代码,但这个想法应该会奏效,你可以在链接文章中再次找到更完整的示例。

有一件事……使用ionic,你想在ionViewDidLoad lifecycle hook中初始化下载URL和照片……它在稍有不同的时间启动,然后angular的ngInitI尝试了这个方法,但我无法再拍照,这让我相信它根本没有初始化。还有其他想法吗?我想我明白了它的要点,但是当我尝试运行它时,它抛出了一个错误:属性“downloadURL”在类型{}上不存在。你知道这是什么吗?你看过console.logresults提供的数据了吗?在我看来,编译器似乎在尝试验证类型是否正确使用,但却不知道结果是什么。尝试添加类快照{downloadURL:string},然后订阅结果:Snapshot[]{},可能是这样。我有点不知道应该在哪里添加它?在forkJoin之前添加类声明,这样编译器就可以找到定义。
// extra import you'll need
import { forkJoin } from "rxjs/observable/forkJoin";

var kuerzel = "teacher";
var lehrerKuerzel = kuerzel.toUpperCase();
var date = Date();
var upload = this.photos.map(i => {
    const ref = firebase.storage().ref(`pruefungen/${lehrerKuerzel}/${date}/${i}`);
    return ref.putString(i, 'data_url');
});
forkJoin(upload).subscribe(results => {
    // results is an array of snapshots
    var db = firebase.firestore().collection(`${lehrerKuerzel}`);
    db.add({
        TestName: pruefungsName,
        Klasse: klasse,
        Abteilung: abteilung,
        Datum: date,
        DownloadURLs: results.map(i => i.downloadURL),
        Length: this.photos.length,
        I: this.photos.length - 1
    });
});