网站搜索

typescript - TypeError: book.isEqual 不是一个函数


在一个类中定义的方法在另一个类中调用时不会被识别为函数。

文件:models/book.model.ts

export class Book {
    constructor(public title: string, public author: string) {
    }

    isEqual (other: Book ): boolean {
    return (this === other);
    }
}

文件:services/books.service.ts

import { Book } from '../models/book.model';
import { Subject } from 'rxjs/Subject';
import * as firebase from 'firebase';
import DataSnapshot = firebase.database.DataSnapshot;

export class BooksService {
    books = [new Book ('', '')]
    booksSubject = new Subject<Book[]>();

    constructor() {
    this.getBooks();
    }

    emitBooks() {
    this.booksSubject.next(this.books);
    }

    getBooks() {
    firebase.database().ref('/books')
        .on('value', 
            (data: DataSnapshot) => 
            {
                this.books = data.val() ? data.val() : [];
                this.emitBooks(); /
            }
        );
    }

    indexOfBook (book: Book) {
    const bookIndex = this.books.findIndex(
        (a_book) => {return book.isEqual (a_book)}
    );
    return bookIndex;
    }

我想在 BooksService 类中调用 Book 类的 'book.isEqual' 方法。book.isEqual 没有被识别为一个函数,为什么?

答案#1

Firebase 返回一些数据,但它只是一个对象:你需要使用 new Book() 根据这些数据创建一个 Book 实例。

firebase.database().ref('/books')
        .on('value', 
            (data: DataSnapshot) => 
            {
                this.books = data.val() ? data.val().map(book => new Book(book[0], book[1])) : [];
                this.emitBooks();
            }
        );
    }

由于我不知道 Firebase 在 val() 中返回什么,这只是一个示例用法,假设数据包含 [author, title] 元组的数组,但你明白意思。也许它实际上是 new Book(book.author, book.title)...

答案#2

我创建了这个 Stackblitz 项目 https://stackblitz.com/edit/firebase-stackoverflow,它运行正常,你可以查看一下

import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import * as firebase from 'firebase/app';

// These imports load individual services into the firebase namespace.
import 'firebase/auth';
import 'firebase/database';
import DataSnapshot = firebase.database.DataSnapshot;

const config = {
    apiKey: "AIzaSyAh-EgWckq1oexuxQ0vVSbKE6jIOGDPcu4",
    authDomain: "yallswall.firebaseapp.com",
    databaseURL: "https://yallswall.firebaseio.com",
    projectId: "yallswall",
    storageBucket: "yallswall.appspot.com",
    messagingSenderId: "109317481518",
    appId: "1:109317481518:web:14342c0b3d54017f"
};

class Book {
    constructor(public title: string, public author: string) {
    }

    isEqual (other: Book): boolean {
     return (this === other);
    }
}

@Component({
  selector: 'my-app',
  template: `
    <ul>
      <li class="text" *ngFor="let book of books">
        {{book.title}} : {{book.author}}, {{book.isEqual(book)}}
      </li>
    </ul>
  `
})
export class AppComponent {

  books: Book[] = [];

  constructor() {
   firebase.initializeApp(config);
   this.getBooks();
  }

  getBooks() {
    firebase.database().ref('books')
      .on('value', (data: DataSnapshot) => {

        this.books = data && data.val().map(bookLike => new Book(bookLike.title, bookLike.author)) || [];

        //the code below works too
        //this.books = [];
        //data && data.forEach(e => {
        //  const bookLike = e.val();
        //  this.books.push(new Book(bookLike.title, bookLike.author));
        //});
      });
  }
}