将 firestore observables 投射到自定义对象 [英] Casting firestore observables to custom objects

查看:29
本文介绍了将 firestore observables 投射到自定义对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 angular 和 firestore 的新手,并试图弄清楚如何将从 firebase 接收到的数据直接转换为模型.这里最好的方法是什么?

I'm new to angular and firestore and trying to figure out how to cast the data received from firebase directly to models. What is the best approach here?

目前我得到了数据,但看起来它没有被转换成一个 Blimp 对象.当我尝试在视图中对其调用 getImageUrl() 时,我收到以下错误消息.

Currently I get the data, but it looks like it's not casted into a Blimp object. When I try to call getImageUrl() on it in the view, I get the following error message.

错误类型错误:_v.context.$implicit.getImageUrl 不是函数

ERROR TypeError: _v.context.$implicit.getImageUrl is not a function

所以我的问题是:将这些 observable 转换为正确的本地模型的最佳和最干净的方法是什么?我原以为标签会默认投射它.

So my question: What is the best and cleanest way to cast these observables to the correct local model? I was expecting the tags to cast it by default.

当前代码

自定义模型类

export class Blimp {


created_at: Date;
file_location: string;
id: string;

constructor() {
    console.log('OBJ');
}

getImageUrl() {
    return "https://*.com" + this.file_location;
}

}

服务类

    import { Injectable } from '@angular/core';
import {Blimp} from '../models/blimp';
import { AngularFirestore } from '@angular/fire/firestore';
import {AngularFireStorage, AngularFireUploadTask} from '@angular/fire/storage';
import {Observable} from 'rxjs';
import {finalize} from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class BlimpService {

   blimps: Observable<Blimp[]>;

  constructor(private fireStore: AngularFirestore, private fireDisk: AngularFireStorage) { }


  getBlimps() {
      this.blimps = this.fireStore.collection<Blimp>('blimps').valueChanges();

      return this.blimps;
  }
}

显示组件

import { Component, OnInit } from '@angular/core';
import {BlimpService} from '../../services/blimp.service';
import {Observable} from 'rxjs';
import {Blimp} from '../../models/blimp';

@Component({
  selector: 'app-blimp-viewer',
  templateUrl: './blimp-viewer.component.html',
  styleUrls: ['./blimp-viewer.component.scss'],
})
export class BlimpViewerComponent implements OnInit {

  blimps: Observable<Blimp[]>;

  constructor(private blimpService: BlimpService) { }

  ngOnInit() {
    this.blimps = this.blimpService.getBlimps();
  }

}

查看

<ul>
  <li *ngFor="let blimp of blimps | async">
      {{ blimp | json}}
      <img [src]="blimp.getImageUrl()" />
  </li>
</ul>

更新 #1

将代码更改为

我现在已将您的示例更改为:getBlimps() {

I now have changed your example to: getBlimps() {

   this.blimps = this.fireStore.collection<Blimp>('blimps')
          .valueChanges()
            pipe(map(b => {
                let blimp = new Blimp();
                blimp.created_at = b.created_at;
                blimp.file_location = b.file_location;
                blimp.id = b.id;

                return blimp;

            }));

      return this.blimps;
  }

这仍然在视图中抱怨在对象上找不到 getImageUrl().

This still complains in the view about the getImageUrl() not being found on the object.

#解决方案

看起来我忘记了一个 .(点)在最后一个代码中

Looks like I forget a . (dot) in the last code

此代码有效:

this.blimps = this.fireStore.collection<Blimp>('blimps')
      .valueChanges()
      .pipe(map(collection => {
            return collection.map(b => {
                let blimp = new Blimp();
                blimp.created_at = b.created_at;
                blimp.file_location = b.file_location;
                blimp.id = b.id;

                return blimp;
            });
        }));

  return this.blimps;

推荐答案

概念:

您不会将 observable 转换为对象模型.可观察对象是具有生命周期的流.
observable它的订阅者发出值,你需要订阅你的 observable 才能在它发出值时得到通知.您还需要关闭订阅,否则订阅将持续到您的可观察完成导致内存泄漏.
我可以看到你正在使用 |async在您的 html 模板 中,它是由 angular 处理的订阅,在需要时自动取消订阅.

Concept :

You don't cast an observable to an object model. An observable is a stream which has a lifecycle.
An observable emits value to its subscribers, you need to subscribe to your observable to be notified when it emits value. You also need to close the subscription or the subscription will last until your observable complete causing memory leaks.
I can see you're using | asyncin your html template, it's a subscription handled by angular that auto-unsubscribe when needed.

您需要将收到的数据映射到 Blimp 对象,可以使用 地图运算符.

You need to map the data you received to a Blimp object, you can use map operator.

blimps$: Observable<Blimp[]>; // naming convention, suffix your observable with $



blimps$ = this.fireStore.collection<Blimp>('blimps')
          .valueChanges()
          .pipe(map(collection => {
                return collection.map(b => {
                    let blimp = new Blimp();
                    blimp.created_at = b.created_at;
                    blimp.file_location = b.file_location;
                    blimp.id = b.id;
                    console.log(blimp);
                    console.log(b);
                    return blimp;
                });
            }));

      return this.blimps;

当我们将 blimps 更改为 blimps$ 时,请更改您的 html 模板:

As we changed blimps to blimps$, change your html template :

*ngFor="let blimp of blimps$ | async"

你可以使用你的类构造函数来初始化你的对象:

EDIT :

You can use your class constructor to initialize your object :

export class Blimp {

created_at?: Date;
file_location?: string;
id?: string;

constructor(blimp: Blimp = {}) {
  this.created_at = blimp.created_at;
  this.file_location = blimp.file_location;
  this.id = blimp.id;
}

getImageUrl() {
    return `https://*.com${this.file_location}`; // use string interpolation here
}



blimps$ = this.fireStore.collection<Blimp>('blimps')
              .valueChanges()
              .pipe(map(collection => {
                    return collection.map(b =>  new Blimp(b));
                }));

这篇关于将 firestore observables 投射到自定义对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆