可观察退订
Observable unsubscribe
我读到每个组件都应该在最后退订所有订阅
ngOnDestroy()
例如。我有以下博客组件:
import { Component, OnInit } from '@angular/core';
import { ISubscription } from "rxjs/Subscription";
import { CarouselConfig } from 'ngx-bootstrap/carousel';
import { BlogPost } from '../shared/blogPost';
import { BlogPostFactory } from '../shared/blogPost-factory';
import { DataService } from '../data.service';
@Component({
selector: 'ca-blog',
templateUrl: './blog.component.html',
styleUrls: ['./blog.component.css'],
providers: [{provide: CarouselConfig, useValue: {interval: 1500, noPause: true}}]
})
export class BlogComponent implements OnInit {
private blogPosts: BlogPost[] = [];
private heartsUp: string[] = [];
private likesUp: string[] = [];
private heartSub: ISubscription;
private likeSub: ISubscription;
constructor(private dataService: DataService) {
window.onscroll = () => {
let windowHeight = "innerHeight" in window ? window.innerHeight : document.documentElement.offsetHeight;
let body = document.body;
let html = document.documentElement;
let docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
let windowBottom = windowHeight + window.pageYOffset;
if(windowBottom >= docHeight) {
let urlSearchParams = { last: this.blogPosts.length };
this.dataService.getBlogPosts(urlSearchParams).subscribe( result => {
for(let i=0; i<result.length; i++){
this.blogPosts.push(BlogPostFactory.fromObject(result[i]));
}
});
}
};
}
ngOnInit() {
this.dataService.getBlogPosts().subscribe( result => {
for(let i=0; i<result.length; i++){
this.blogPosts.push(BlogPostFactory.fromObject(result[i]));
}
});
}
incrementHearts(index) : void {
let idIndex : number = this.heartsUp.indexOf(this.blogPosts[index].id);
if(idIndex != -1){
this.blogPosts[index].hearts--;
this.heartsUp.splice(idIndex, 1);
} else {
this.blogPosts[index].hearts++;
this.heartsUp.push(this.blogPosts[index].id);
}
this.heartSub = this.dataService.editBlogPost(this.blogPosts[index].id, { hearts: this.blogPosts[index].hearts }).subscribe();
}
incrementLikes(index) : void {
let idIndex : number = this.likesUp.indexOf(this.blogPosts[index].id);
if(idIndex != -1){
this.blogPosts[index].likes--;
this.likesUp.splice(idIndex, 1);
} else {
this.blogPosts[index].likes++;
this.likesUp.push(this.blogPosts[index].id);
}
this.likeSub = this.dataService.editBlogPost(this.blogPosts[index].id, { likes: this.blogPosts[index].likes }).subscribe();
}
ngOnDestroy() {
// this.likeSub.unsubscribe();
// this.heartSub.unsubscribe();
}
}
但是当我取消注释 ngOnDestroy()
函数中的两行时,我的网站崩溃了。它说 heartSub
和 likeSub
是未定义的。适当的 HTML 文件如下所示:
<div class="container">
<div *ngFor="let blogPost of blogPosts; let i=index">
<div *ngIf="i !== 0">
<hr class="my-5">
</div>
<div class="row">
<div class="col">
<article>
<section>
<header style="" class="mb-4">
<h1 style="display:inline" class="m-0 p-0">{{ blogPost.title }}</h1><small style="opacity:0.5" class="d-block d-sm-inline ml-sm-3">zuletzt bearbeitet am {{ blogPost.lastEdited | date }} von <a href="#" style="color:black"><strong>{{ blogPost.author.username }}</strong></a></small>
<p class="mt-1 mt-sm-auto"><i class="fa fa-tags mr-2"></i><a *ngFor="let hashtag of blogPost.hashtags" href="#" class="badge badge-secondary mr-2">#{{ hashtag }}</a></p>
</header>
<div class="m-0 p-0" [innerHTML]="blogPost.body">
</div>
<div>
<small class="heartUp"><a (click)="incrementHearts(i)" [ngStyle]="{'color':heartsUp.includes(blogPost.id) ? '#E63946' : 'rgba(0,0,0,0.5)'}"><i class="fa fa-heart mr-1"></i>{{ blogPost.hearts }}</a></small>
<small class="likeUp"><a (click)="incrementLikes(i)" [ngStyle]="{'color':likesUp.includes(blogPost.id) ? '#3b5998' : 'rgba(0,0,0,0.5)'}"><i class="fa fa-thumbs-up mr-1"></i>{{ blogPost.likes }}</a></small>
<small class="reply"><a><i class="fa fa-mail-reply mr-1"></i>Reply</a></small>
</div>
<div>
<h2 class="my-3">Kommentare</h2>
<div class="row no-gutters">
<div class="col-auto mr-3">
<img src="https://semantic-ui.com/images/avatar/small/jenny.jpg" class="img-fluid">
</div>
<div class="col">
<h5 style="margin:0;padding:0;display:inline">Joe Henderson</h5><small style="display:inline;margin:0;padding:0;opacity:0.5" class="ml-2"> 1 day ago</small>
<div style="margin:0;padding:0">The hours, minutes and seconds stand as visible reminders that your effort put them all there.
Preserve until your next run, when the watch lets you see how Impermanent your efforts are.</div>
<div>and some other text</div>
<small style="margin:0;padding:0;opacity:0.5;margin-right:10px"><i class="fa fa-heart mr-1"></i>3</small>
<small style="margin:0;padding:0;opacity:0.5;margin-right:10px"><i class="fa fa-thumbs-o-up mr-1"></i>12</small>
<small style="margin:0;padding:0;opacity:0.5"><i class="fa fa-mail-reply mr-1"></i>Reply</small>
</div>
</div>
</div>
</section>
</article>
</div>
</div>
</div>
</div>
它使用 CSS 框架 Bootstrap,但这应该无关紧要。所以我的网站加载了很多 post,每个 post 都有一个喜欢和一个心形按钮,用户可以上下按下。如果它已发布,那么我会在数据库中更新我的 post。
最后我想退订,但是我不能。我不知道出了什么问题。 :(
不过,我认为赞成票和反对票写得真的很糟糕,但是怎么办呢?我感谢任何帮助。 :)
此致,
斯文
我会在您有订阅调用的组件中创建一个新的主题。
private ngUnsubscribe: Subject = new Subject();
然后,在你调用的 ngOnDestroy 中
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
在每次订阅之前,您都需要等待:
this.likeSub = this.dataService.editBlogPost(this.blogPosts[index].id, { likes: this.blogPosts[index].likes })
.takeUntil(this.ngUnsubscribe)
.subscribe();
这是我在申请中使用的方法,您可以在此处阅读更多相关信息:
我同意@Filip,我按照他描述的方式走了同样的路。
关于您当前的问题。如果函数 incrementLikes()
和 incrementHearts()
没有被调用,那么这两个订阅肯定是 undefined
。
Sv 恩,如果你不执行 incrementLikes() 或 incrementHearts() 你的变量就没有值。你可以做到
ngOnDestroy() {
if (this.likeSub) //if exist
this.likeSub.unsubscribe();
if (this.heartSub) //if exist
this.heartSub.unsubscribe();
}
菲利普,你不需要使用主题,只是一个布尔变量
this.dataService.editBlogPost(..)
.takeWhile(() => this.isAlive)
.subscribe(...)
我读到每个组件都应该在最后退订所有订阅
ngOnDestroy()
例如。我有以下博客组件:
import { Component, OnInit } from '@angular/core';
import { ISubscription } from "rxjs/Subscription";
import { CarouselConfig } from 'ngx-bootstrap/carousel';
import { BlogPost } from '../shared/blogPost';
import { BlogPostFactory } from '../shared/blogPost-factory';
import { DataService } from '../data.service';
@Component({
selector: 'ca-blog',
templateUrl: './blog.component.html',
styleUrls: ['./blog.component.css'],
providers: [{provide: CarouselConfig, useValue: {interval: 1500, noPause: true}}]
})
export class BlogComponent implements OnInit {
private blogPosts: BlogPost[] = [];
private heartsUp: string[] = [];
private likesUp: string[] = [];
private heartSub: ISubscription;
private likeSub: ISubscription;
constructor(private dataService: DataService) {
window.onscroll = () => {
let windowHeight = "innerHeight" in window ? window.innerHeight : document.documentElement.offsetHeight;
let body = document.body;
let html = document.documentElement;
let docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
let windowBottom = windowHeight + window.pageYOffset;
if(windowBottom >= docHeight) {
let urlSearchParams = { last: this.blogPosts.length };
this.dataService.getBlogPosts(urlSearchParams).subscribe( result => {
for(let i=0; i<result.length; i++){
this.blogPosts.push(BlogPostFactory.fromObject(result[i]));
}
});
}
};
}
ngOnInit() {
this.dataService.getBlogPosts().subscribe( result => {
for(let i=0; i<result.length; i++){
this.blogPosts.push(BlogPostFactory.fromObject(result[i]));
}
});
}
incrementHearts(index) : void {
let idIndex : number = this.heartsUp.indexOf(this.blogPosts[index].id);
if(idIndex != -1){
this.blogPosts[index].hearts--;
this.heartsUp.splice(idIndex, 1);
} else {
this.blogPosts[index].hearts++;
this.heartsUp.push(this.blogPosts[index].id);
}
this.heartSub = this.dataService.editBlogPost(this.blogPosts[index].id, { hearts: this.blogPosts[index].hearts }).subscribe();
}
incrementLikes(index) : void {
let idIndex : number = this.likesUp.indexOf(this.blogPosts[index].id);
if(idIndex != -1){
this.blogPosts[index].likes--;
this.likesUp.splice(idIndex, 1);
} else {
this.blogPosts[index].likes++;
this.likesUp.push(this.blogPosts[index].id);
}
this.likeSub = this.dataService.editBlogPost(this.blogPosts[index].id, { likes: this.blogPosts[index].likes }).subscribe();
}
ngOnDestroy() {
// this.likeSub.unsubscribe();
// this.heartSub.unsubscribe();
}
}
但是当我取消注释 ngOnDestroy()
函数中的两行时,我的网站崩溃了。它说 heartSub
和 likeSub
是未定义的。适当的 HTML 文件如下所示:
<div class="container">
<div *ngFor="let blogPost of blogPosts; let i=index">
<div *ngIf="i !== 0">
<hr class="my-5">
</div>
<div class="row">
<div class="col">
<article>
<section>
<header style="" class="mb-4">
<h1 style="display:inline" class="m-0 p-0">{{ blogPost.title }}</h1><small style="opacity:0.5" class="d-block d-sm-inline ml-sm-3">zuletzt bearbeitet am {{ blogPost.lastEdited | date }} von <a href="#" style="color:black"><strong>{{ blogPost.author.username }}</strong></a></small>
<p class="mt-1 mt-sm-auto"><i class="fa fa-tags mr-2"></i><a *ngFor="let hashtag of blogPost.hashtags" href="#" class="badge badge-secondary mr-2">#{{ hashtag }}</a></p>
</header>
<div class="m-0 p-0" [innerHTML]="blogPost.body">
</div>
<div>
<small class="heartUp"><a (click)="incrementHearts(i)" [ngStyle]="{'color':heartsUp.includes(blogPost.id) ? '#E63946' : 'rgba(0,0,0,0.5)'}"><i class="fa fa-heart mr-1"></i>{{ blogPost.hearts }}</a></small>
<small class="likeUp"><a (click)="incrementLikes(i)" [ngStyle]="{'color':likesUp.includes(blogPost.id) ? '#3b5998' : 'rgba(0,0,0,0.5)'}"><i class="fa fa-thumbs-up mr-1"></i>{{ blogPost.likes }}</a></small>
<small class="reply"><a><i class="fa fa-mail-reply mr-1"></i>Reply</a></small>
</div>
<div>
<h2 class="my-3">Kommentare</h2>
<div class="row no-gutters">
<div class="col-auto mr-3">
<img src="https://semantic-ui.com/images/avatar/small/jenny.jpg" class="img-fluid">
</div>
<div class="col">
<h5 style="margin:0;padding:0;display:inline">Joe Henderson</h5><small style="display:inline;margin:0;padding:0;opacity:0.5" class="ml-2"> 1 day ago</small>
<div style="margin:0;padding:0">The hours, minutes and seconds stand as visible reminders that your effort put them all there.
Preserve until your next run, when the watch lets you see how Impermanent your efforts are.</div>
<div>and some other text</div>
<small style="margin:0;padding:0;opacity:0.5;margin-right:10px"><i class="fa fa-heart mr-1"></i>3</small>
<small style="margin:0;padding:0;opacity:0.5;margin-right:10px"><i class="fa fa-thumbs-o-up mr-1"></i>12</small>
<small style="margin:0;padding:0;opacity:0.5"><i class="fa fa-mail-reply mr-1"></i>Reply</small>
</div>
</div>
</div>
</section>
</article>
</div>
</div>
</div>
</div>
它使用 CSS 框架 Bootstrap,但这应该无关紧要。所以我的网站加载了很多 post,每个 post 都有一个喜欢和一个心形按钮,用户可以上下按下。如果它已发布,那么我会在数据库中更新我的 post。
最后我想退订,但是我不能。我不知道出了什么问题。 :( 不过,我认为赞成票和反对票写得真的很糟糕,但是怎么办呢?我感谢任何帮助。 :)
此致, 斯文
我会在您有订阅调用的组件中创建一个新的主题。
private ngUnsubscribe: Subject = new Subject();
然后,在你调用的 ngOnDestroy 中
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
在每次订阅之前,您都需要等待:
this.likeSub = this.dataService.editBlogPost(this.blogPosts[index].id, { likes: this.blogPosts[index].likes })
.takeUntil(this.ngUnsubscribe)
.subscribe();
这是我在申请中使用的方法,您可以在此处阅读更多相关信息:
我同意@Filip,我按照他描述的方式走了同样的路。
关于您当前的问题。如果函数 incrementLikes()
和 incrementHearts()
没有被调用,那么这两个订阅肯定是 undefined
。
Sv 恩,如果你不执行 incrementLikes() 或 incrementHearts() 你的变量就没有值。你可以做到
ngOnDestroy() {
if (this.likeSub) //if exist
this.likeSub.unsubscribe();
if (this.heartSub) //if exist
this.heartSub.unsubscribe();
}
菲利普,你不需要使用主题,只是一个布尔变量
this.dataService.editBlogPost(..)
.takeWhile(() => this.isAlive)
.subscribe(...)