Angular firebase为什么同样的功能只能工作一次?

时间:2018-03-27 14:23:01

标签: javascript angular firebase firebase-realtime-database

我使用了一些组件上传了upload.service和2个不同的模块。

  

upload.service,upload.ts导入到components->

     

Upload.module(

     

upload.component(一切正常(我可以上传并获取照片)   来自数据库的url数据)

     

     

Ui.module)

     

upload.component(功能相同,但我看不到照片,没有网址)

     

工作组件(upload.component):

import { Component, OnInit } from '@angular/core';

import { UploadService } from '../shared/upload.service';
import { Upload } from '../shared/upload';

import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'uploads-list',
  templateUrl: './uploads-list.component.html',
  styleUrls: ['./uploads-list.component.scss'],
})
export class UploadsListComponent implements OnInit {

  uploads: Observable<Upload[]>;
  showSpinner = true;

  constructor(private upSvc: UploadService) { }

  ngOnInit() {
    this.uploads = this.upSvc.getUploads();
    this.uploads.subscribe(() => this.showSpinner = false);
  }
}

不工作的组件(ui.component 0 errors):

import {Component, OnInit} from '@angular/core';
import { UploadService } from "../../uploads/shared/upload.service";
import { Upload } from "../../uploads/shared/upload";
import { Observable } from "rxjs/Observable";

@Component({
  selector: 'top-nav',
  templateUrl: './top-nav.component.html',
  styleUrls: ['./top-nav.component.scss'],
})
export class TopNavComponent implements OnInit {
  uploads: Observable<Upload[]>;
  show = false;
  showSpinner = true;
  toggleCollapse() {
    this.show = !this.show;
  }

  constructor(private upSvc: UploadService) { }

  ngOnInit() {
    this.uploads = this.upSvc.getUploads();
    console.log("paimama upload :", this.uploads)
    this.uploads.subscribe(() => this.showSpinner = false);
  }

}

我认为主要的问题是我试图在两个不同的模块 - 组件中使用这些函数和变量。如何检索它以便它可以工作?

编辑(我正在调用的函数):

 getUploads() {
    this.uploads = this.db.list(`${this.auth.userId}`).snapshotChanges().map((actions) => {
      return actions.map((a) => {
        const data = a.payload.val();
        const $key = a.payload.key;
        return { $key, ...data };
      });

    });
    return this.uploads;
  }

Html(在upload.component中工作):

<h3>File Uploads</h3>

<div *ngFor="let upload of uploads | async">
  <upload-detail [upload]='upload'></upload-detail>
  <img src="{{upload.url}}" alt="">
</div>

<loading-spinner *ngIf="showSpinner"></loading-spinner>

<hr>

<upload-form></upload-form>

HTML(不工作ui.component)

<div *ngFor="let upload of uploads | async">
      <img src="{{upload.url}}" alt="">
    </div>

1 个答案:

答案 0 :(得分:0)

每次调用getUploads()方法时,您似乎都在重新初始化服务可观察性。这会导致每个组件订阅不同的observable,因此它们不会同步。

如果您希望所有组件订阅同一个流,请不要这样做。

更改此内容:

getUploads() {
    this.uploads = this.db.list(`${this.auth.userId}`).snapshotChanges().map((actions) => {
        return actions.map((a) => {
            const data = a.payload.val();
            const $key = a.payload.key;
            return { $key, ...data };
        });

    });

    return this.uploads;
}

对此:

getUploads() {
    if (!this.uploads) {
        this.uploads = this.db.list(`${this.auth.userId}`).snapshotChanges().map((actions) => {
            return actions.map((a) => {
                const data = a.payload.val();
                const $key = a.payload.key;
                return { $key, ...data };
            });
        });
    }

    return this.uploads;
}

现在每个组件都应该获得完全相同的可观察流。

如果这没有帮助,请告诉我。

<强>更新

您可以采取的另一种方法是创建自定义主题并将其用作可观察对象。在两个组件中订阅该observable,当您从db上传时,您可以将上传添加到流中。每个组件都会获得您添加到该流的上传。

@Injectable()
export class UploadService {
    uploadSubject: ReplaySubject<Upload> = new ReplaySubject();
    upload$: Observable<Upload> = this.uploadSubject.asObservable();

    getUploads() {
        this.http.get(url).subscribe((upload: Upload) => {
            this.uploadSubject.next(upload);
        });
    }
}

现在在任何组件中,您只需订阅upload$,只要调用getUploads(),订阅upload$的每个组件都会获得值。

export class Component1 {
    upload: Upload;

    constructor(private uploadService: UploadService) {
        uploadService.upload$.subscribe((upload: Upload) => this.upload = upload);
    }
}

export class Component2 {
    upload: Upload;

    constructor(private uploadService: UploadService) {
        uploadService.upload$.subscribe((upload: Upload) => this.upload = upload);
    }
}

使用这种方法,只需确保在某处调用getUploads,因为组件没有调用它;他们只是在倾听它将播出的价值。

更新2:

现在我正在修改您的代码以使用上面的示例。由于这是使用您的代码,它可能无法正常工作,因为我可能会遗漏您环境中的某些内容。但最初的&#34;更新&#34;以上工作100%,所以使用它作为指导,以使您的代码工作。只需阅读代码并确保您了解它的作用,您就会发现它可以用于您正在做的事情。

<强> UploadService:

@Injectable()
export class UploadService {
    uploadStream: ReplaySubject<Upload[]> = new ReplaySubject();
    uploads$: Observable<Upload[]> = this.uploadStream.asObservable();

    constructor() {
        this.getUploads();
    }

    getUploads() {
        this.db.list(`${this.auth.userId}`)
            .map((actions: Action[]) => {
                return actions.map((action: Action) => {
                    const data = action.payload.val();
                    const $key = action.payload.key;

                    return new Upload({ $key, ...data });
                });
            })
            .subscribe((uploads: Upload[]) => {
                this.uploadStream.next(uploads);
            });
    }
}

<强> UploadsListComponent:

import { Component } from '@angular/core';

import { UploadService } from '../shared/upload.service';

@Component({
  selector: 'uploads-list',
  templateUrl: './uploads-list.component.html',
  styleUrls: ['./uploads-list.component.scss'],
})
export class UploadsListComponent {
  constructor(public uploadService: UploadService) {}
}

UploadListComponent模板:

<h3>File Uploads</h3>

<div *ngFor="let upload of uploadService.uploads$ | async">
  <upload-detail [upload]='upload'></upload-detail>
  <img src="{{upload.url}}" alt="">
</div>

<loading-spinner *ngIf="showSpinner"></loading-spinner>

<hr>

<upload-form></upload-form>

现在,您可以在第二个组件上采用与上述相同的组件方法。