Ошибка типа: book.isEqual не является функцией - PullRequest
1 голос
/ 17 июня 2019

Метод, определенный в классе, не распознается как функция при вызове из другого класса.

file: models / book.model.ts

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

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

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

Я хотел бы вызвать метод book.isEqual класса Book в классе BooksService.book.isEqual не распознается как функция, почему?

Ответы [ 3 ]

2 голосов
/ 17 июня 2019

Firebase возвращает некоторые данные, но это просто объект: вам нужно создать Book экземпляр из этих данных с помощью new 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) ...

1 голос
/ 18 июня 2019

Я создал этот проект 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));
        //});
      });
  }
}
1 голос
/ 18 июня 2019

Создание большого количества новых экземпляров классов, которые требуются текущему коду, является трудоемким и, вероятно, ненужным.

Вот альтернатива, в которой вместо этого используется interface s (которые вообще не передаются в JavaScript) изначительно упрощенный поиск по индексу.

export interface Book {
    title: string;
    author: string;
}

и затем в сервисе, небольшое изменение для преобразования вашего возврата в Book[]:

this.books = data.val() ? (data.val() as Book[]) : [];

Затем вы можете использовать вспомогательную функциюи полностью отказаться от класса.Раньше он использовал сочетание функций со стрелками и операторов возврата в скобках, и помощник isEqual не был необходим, поскольку все это можно сократить до:

indexOfBook = (needle: Book) => this.books.findIndex(
    book => book.author == needle.author && book.title == needle.title
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...