未定义数组,尽管它在dom角度6中呈现

时间:2018-10-08 09:38:51

标签: angular typescript rxjs undefined

这是我的“书籍”组件,其中包含我尝试控制日志的书籍数组。它记录了一个undefined,但在使用*ngFor之后,它在DOM中正确显示。

import { Component, OnInit } from '@angular/core';
import { BooksService } from '../shared/books.service';
import { ActivatedRoute, Params } from '@angular/router';
import { Book } from './book.model';

@Component({
  selector: 'app-books',
  templateUrl: './books.component.html',
  styleUrls: ['./books.component.scss']
})
export class BooksComponent implements OnInit {
  books: Book[];
  filteredBooks: Book[];
  id: string;

  constructor(
    private booksService: BooksService,
    private route: ActivatedRoute
  ) {}

  ngOnInit() {

    this.booksService.getJson()
      .subscribe(response => (
        this.books = response.json().books)
      );

      console.log(this.books) //undefined;

    this.route.params.subscribe((params: Params) => {
      this.id = params['id'];
    });
    const filter = this.books.filter(book => book.author === this.id);
    console.log(filter);
  }
}

3 个答案:

答案 0 :(得分:2)

欢迎堆栈溢出!我在您的代码中看到的问题是,您试图在获取books数组之前对其进行打印。

您从getJson()调用的函数BooksService是异步调用。意思是说,我们不知道此函数获取books数组可能需要多长时间(在某些情况下甚至可能会失败)。

如果只想打印书籍列表,则可以执行此操作(注意,我添加了一个错误块来处理错误):

ngOnInit() {

  this.booksService.getJson()
    .subscribe(
      response => { // on success
        this.books = response.json().books)
        console.log(this.books); // shows your books!
      },
      error => { // on failure
        console.log('Error Occurred:' + JSON.stringify(error));
      }
    );
  // remaining code ...
}

此外,在模板(html)中,您还必须添加*ngIf才能遍历这些书:

<div *ngIf="books">
  <div *ngFor="let book of books">
    <div>{{book.name || 'unknown'}}</div>
  </div>
</div>

但是,我强烈建议您从以下来源之一中阅读 promise链接 Promise.race 或什至回调函数 。您也可以自由地在其他地方引用,但是在我看来,下面的第一个站点(MDN)是引用与javascript相关的任何内容的好地方:)

答案 1 :(得分:1)

您对这部分代码有疑问:

this.booksService.getJson()
  .subscribe(response => (
    this.books = response.json().books)
  );

  console.log(this.books) //undefined;

HTTP调用是异步的,因此.subscribe()中的代码将在您的console.log(this.books) //undefined;之后运行。

console.log放入.subscribe()方法中。

this.booksService.getJson()
      .subscribe(response => (
        this.books = response.json().books);
        console.log(this.books) //undefined;
      );

实际上-您还从id中读取了route.params-这也是一个异步任务。在这种情况下,您应该将booksService.getJSON()流与route.params流结合起来,然后执行以下操作:

Observable.combineLatest(
    this.route.params,    //1st stream
    this.booksService.getJson().map(res => res.json().books) //2nd stream   
)
.do((values: any[]) => {
    const id = values[0]['id']; //params from 1st stream
    const allBooks = values[1];        //already mapped books from 2nd stream

    this.filteredBooks = allBooks.filter(book => book.author === id);

}).subscribe();

答案 2 :(得分:0)

Angular多次渲染您的books。起初也是undefined

尝试将您的filter代码放入您的subscribe