gpt4 book ai didi

angular - 响应式(Reactive)开发 | RxJS 异步管道不工作

转载 作者:行者123 更新时间:2023-12-02 03:09:23 25 4
gpt4 key购买 nike

我正在尝试通过将服务中的旧方法转换为在 Observable 中根本不订阅来学习 Angular 中的响应式(Reactive)开发。到目前为止,我已经转换的最简单的方法是 getAll 方法。我现在想要的是,当我在卡片列表中选择一张卡片时,我将被重定向到另一个页面以查看其详细信息。考虑我当前正在使用的以下代码。

服务

@Injectable({
'providedIn': 'root'
})
export class CardService {

private selectedCardIdSubject = new Subject<number>();
selectedCardIdAction$ = this.selectedCardIdSubject.asObservable();

/**
* Retrieve single card based on card id.
*/
card$ = this.selectedCardIdAction$
.pipe(
tap(id => console.log(`card$: ${this._cardsApi}/${id}`)),
concatMap(id =>
this._http.get<Card>(`${this._cardsApi}/${id}`)
.pipe(
map(card => ({
...card,
imageUrl: `${this._cardImageApi}/${card.idName}.png`
}))
)
),
catchError(this.handleError)
);

onSelectedCardId(id: number) {
this.selectedCardIdSubject.next(id);
console.log(`onSelectedCardId: ${id}`)
}
}

组件

@Component({})
export class CardDetailsComponent {
constructor(private _cardService: CardService,
private route: ActivatedRoute) {

this.selectedCardId = this.route.snapshot.params['id'];
this._cardService.onSelectedCardId(this.selectedCardId);
}

card$ = this._cardService.card$;
}

HTML

<div class="container mb-5" *ngIf="card$ | async as card">
<p>{{ card.name }}</>
</div>

在上面的代码中,当重定向时,它不会呈现我的简单 HTML 来显示所选卡片的名称。我正在使用 [routerLink] 在卡详细信息页面中进行重定向。

卡片列表组件

<div *ngIf="cards$ | async as cards">
<div class="col-md-1 col-4 hover-effect" *ngFor='let card of cards'>
<a class="d-block mb-1">
<figure>
<img class="img-fluid img-thumbnail" [src]='card.imageUrl' [title]='card.name' [alt]='card.name'
[routerLink]="['/cards', card.id]" />
</figure>
</a>
</div>
</div>

谁能告诉我这里发生了什么?

最佳答案

它不起作用的原因是你的 $card 是在构造函数中发射后订阅的,此时 View 尚未渲染,这意味着 aysnc 管道尚未就位。

该场景与下面的代码顺序非常相似,因此您没有收到更新

// constructor
const a=new Subject()
a.next('some value')
// rendering
a.subscribe(console.log) // never triggered

有两种方法可以解决这个问题:

  • 首先使用 shareReplay(1) 缓存最新值,因此订阅时它始终发出最后一个值

    selectedCardIdAction$ = this.selectedCardIdSubject.asObservable().pipe(shareReplay(1));

或使用BehaviorSubject

private selectedCardIdSubject = new BehaviorSubject<number | null>(null);
  • 第二次将 .next() 移动到 ngAfterViewInit - 它在创建 View 并订阅异步管道后触发

我个人会选择第一种方法,如果你的代码没有太多缺陷,结果会更加一致

关于angular - 响应式(Reactive)开发 | RxJS 异步管道不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58127740/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com