离子 3 中的阵列推入不起作用

Posted

技术标签:

【中文标题】离子 3 中的阵列推入不起作用【英文标题】:Array pushing in ionic 3 not working 【发布时间】:2018-05-25 04:10:10 【问题描述】:

我正在使用 ionic 3 和 firebase 构建应用。基本上,我希望能够拍摄多张照片,将它们上传到 Firebase 存储,然后获取指向这些照片的链接并将这些链接放在 Firestore 中的文档中。但是,我遇到了包含 downloadURLs 的数组的奇怪行为。如果我运行该函数一次,它会将文档上传到 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 语句总是正确的,因为某些原因 i 总是 == 长度。因此,集合中的项目总是太多。

【问题讨论】:

一件事...使用 ionic 你想在 ionViewDidLoad 生命周期钩子中初始化 downloadURLsphotos...它的触发时间与 angular 的 ngInit 略有不同 我试过这个,但是我不能再拍照,这让我相信它根本没有被初始化。还有其他想法吗? 【参考方案1】:

上传函数res.putString 异步工作,这意味着您的while 循环运行到完成文件实际上传之前,所以this.downloadURLs === [] 在添加记录时,并且仅稍后填充,因为照片一张一张完成。

在添加记录之前,您应该等待所有上传完成,因此您已经有所有下载 url 可以写入数据库。

一种方法是使用 Observable ForkJoin,在 this page 中描述为:

如果您熟悉 Promises,这与 Promise.all() 非常相似。 forkJoin() 运算符允许我们获取 Observable 列表并并行执行它们。一旦列表中的每个 Observable 发出一个值,forkJoin 就会发出一个 Observable 值,该值包含列表中 Observables 中所有已解析值的列表。

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

在您的特定情况下,我建议您在循环中进行存储调用数组,然后使用 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
    );
);

尚未测试代码,但该想法应该可行,您可以再次在链接文章中找到更完整的示例。

【讨论】:

我想我明白了它的要点,但是当我尝试运行它时,它会吐出这个错误:属性 'downloadURL' 在 type 上不存在。你知道这是什么吗? 你看过console.log(results)提供的数据了吗? 在我看来,编译器正在尝试验证类型是否正确使用,但不知道结果是什么。尝试添加class Snapshot downloadURL: string ,然后添加subscribe(results: Snapshot[] ),可以。 我有点菜鸟,我应该在哪里添加这个? 在forkJoin之前添加类声明,以便编译器找到定义。【参考方案2】:

使用promisesPromise.all 组成的数组:

...

let promises = [];
while(i < length)
  promises.push(new Promise(resolve, reject) 
    const ref = firebase.storage().ref(`pruefungen/$lehrerKuerzel/$date/$i`);
    ref.putString(this.photos[i], 'data_url').then((snapshot) => 
      this.downloadURLs.push(snapshot.downloadURL);
      resolve();
    ).catch(e => 
      console.log(e);
      reject();
    );
  )
  i++;


Promise.all(promises).then(() => 
  var db = firebase.firestore().collection(`$lehrerKuerzel`);
  db.add(
    TestName: pruefungsName,
    Klasse: klasse,
    Abteilung: abteilung,
    Datum: date,
    DownloadURLs: this.downloadURLs,
    Length: length,
    I: i
  );
)

【讨论】:

以上是关于离子 3 中的阵列推入不起作用的主要内容,如果未能解决你的问题,请参考以下文章

离子 3 警报;调用dismiss()后调用present()不起作用

当我按下屏幕离子 3 时菜单不起作用

平台就绪中的离子闪屏 hide() 方法不起作用

Ionic3 - 离子元素/组件在 innerHTML 中不起作用

NodeJs 推入数组在异步函数中不起作用

后台服务科尔多瓦离子应用程序。背景插件在 ios 8.3 上不起作用