HttpClient角度.将数据保存在变量中,并从其他组件进行访问.空或未定义



我有一个get与Httpclient的请求。我遇到的问题是,当我试图从其他组件访问此请求加载的变量时。当我试着去做的时候,我发现它是空的。

这是正在使用的方法:

import { HttpClient } from '@angular/common/http';
...
getBooks(page: string) {
let url = `${this.urlAPI}books?page=${page}`;
return this.http.get<Book[]>(url).pipe(map((res: Book[]) => res));
}

这是component.ts中的代码。它是递归的,因为api每次只加载50。

import { ApiService } from 'src/app/services/api.service';
...
books: Book[] = [];
...
constructor(public auth: AuthService, public _api: ApiService, private router: Router) {
this.loadBooks(1);
}
...
loadBooks(page: number) {
this._api.getBooks(page.toString()).subscribe((resp: Book[]) => {
this.books = this.books.concat(resp);
if (resp.length !== 0)
this.loadBooks(page + 1)
else{
...
}
});
}

这是从子组件加载变量的方法:

import { Component, OnInit, Input } from '@angular/core';
import { BooksComponent } from '../../tab/books/books.component';
...
import { ApiService } from 'src/app/services/api.service';

@Component({
selector: 'app-book',
templateUrl: './book.component.html',
styleUrls: ['./book.component.scss'],
providers: [BooksComponent]
})
export class BookComponent implements OnInit {
book: Book = new Book();
constructor(private bc:BooksComponent, public _api: ApiService, private route: ActivatedRoute) {
console.log(bc.books);
...
}

在父组件之后对子组件进行的调用。我也知道这是异步调用,所以直到它没有完成,我还没有填充变量。但我在看到父组件中的所有数据后调用此函数。我不明白为什么如果我填充了变量,那么这个数组在其他组件中是空的。谢谢你的回答。

更新:这是我用来调用图书组件的HTML:

<ng-container matColumnDef="detail">
<th mat-header-cell *matHeaderCellDef> Details </th>
<td mat-cell *matCellDef="let row">
<button mat-button (click)="detail(row.url)">
<mat-icon>info</mat-icon>
</button>
</td>
</ng-container>

它是有棱角材料表的一部分。我使用该功能转到书本组件。

这就是NgModule:

@NgModule({
declarations: [
AppComponent,
HomeComponent,
ListComponent,
NavbarComponent,
ProfileComponent,
BooksComponent,
BookComponent
],
imports: [
BrowserModule,
AppRoutingModule,
APP_ROUTING,
MaterialModule,
HttpClientModule
],
providers: [ApiService],
bootstrap: [AppComponent]
})
export class AppModule { }

父组件是第二个代码。其余的代码是关于MatPaginator、MatSort或MatTableDataSource的。

更新2:

我把代码留在GitHub:WikiIceAndFire

从提供程序数组中删除BooksComponent。您不希望子组件提供自己的BooksComponent实例,而是希望angular获得已经存在的实例,即父组件。

@Component({
selector: 'app-book',
templateUrl: './book.component.html',
styleUrls: ['./book.component.scss'],
providers: [BooksComponent] // <= remove this
})
export class BookComponent implements OnInit {...}

Angular中有一个组件注入器树。当您尝试注入一些东西时,您只需将令牌作为构造函数参数进行传递。组件注入器开始在组件提供程序上查找该令牌。在这种情况下,组件注入器在其自己的提供程序中找到了一个实例,该实例不是所需的实例(父组件(,因此它停止了将要进行的递归搜索(通过询问父组件的组件注入者,该注入器将返回正确的实例(。

我注意到了几件事:
1。不要在providers中使用Component,它主要用于Services或其他providers
2。使用服务或@Input()/@Output()在组件之间共享数据
3。尽量避免嵌套订阅和递归订阅,因为这将是内存泄漏的主要风险

现在是我的改进想法:我假设图书组件集成为一本书的显示组件。

这是book.component.ts

import { Component, OnInit, Input } from '@angular/core';
...
import { ApiService } from 'src/app/services/api.service';

@Component({
selector: 'app-book',
templateUrl: './book.component.html',
styleUrls: ['./book.component.scss'],
})
export class BookComponent implements OnInit {
@Input() book: Book = new Book();
constructor(public _api: ApiService, private route: ActivatedRoute) {
}
ngOnInit() {
console.log(this.book) // either is new Book() or the given book from its parent (look parent .html)
}
...
import { ApiService } from 'src/app/services/api.service';
import { Subject } from 'rxjs'
import { mergeMap } from 'rxjs/operators'
@Component({
...
})
export class ParentComponent implements OnInit, OnDestroy {
...
books: Book[] = [];
private loadPage = new Subject<number>()
...
constructor(public auth: AuthService, public _api: ApiService, private router: Router) {
//
} 
ngOnInit() {
this.loadPage
.pipe(
mergeMap(number => this.loadBooks(number),
(page, books) => {
if (books.length !== 0) {
this.loadPage.next(page+1)
}
return books
}
)
).subscribe({
next: books => {
this.books = this.books.concat(books)
};
error: () => console.log("error");
})    
}
ngOnDestroy() {
this.loadPage.complete()
}
loadBooks(page: number) {
return this._api.getBooks(page.toString())
}

Api服务保持不变。

parent.component.html:

<app-book *ngFor="let book of books" [book]="book"></app-book>

最新更新