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

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

问题描述

我是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.

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

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

所以我的问题是:将这些可观测对象转换为正确的局部模型的最佳和最干净的方法是什么?我期望这些标签会默认投放.

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

}

服务等级

Service class

    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以便在其产生价值时得到通知.您还需要关闭订阅,否则订阅将一直持续到可观察到的完成导致内存泄漏.
我可以看到您正在使用 |在您的 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可观察对象投射到自定义对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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