可观察的取消订阅

时间:2018-02-11 23:12:45

标签: javascript angular redux-observable

我已经读过,每个组件都应该取消订阅最后的所有订阅

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()函数中的两行时,我的网站崩溃了。它说heartSublikeSub未定义。相应的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,但这不重要。所以我的网站加载了很多帖子,每个帖子都有一个喜欢和一个心形按钮,可以由用户上下按下。如果它已经发布,那么我在数据库中更新我的帖子。

我想在最后取消订阅,但我不能。我不知道这个问题是什么。 :( 不过,我认为上下投票真的很糟糕,但怎么可能呢?我感谢任何帮助。 :)

祝你好运, 斯文

3 个答案:

答案 0 :(得分:0)

我会在你的组件中创建一个新主题的路线,在那里你有订阅电话。

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();

这是我在我的应用程序中使用的方法,你可以在这里阅读更多相关信息:

Angular/RxJs When should I unsubscribe from `Subscription`

答案 1 :(得分:0)

我同意@Filip,我和他描述的路线相同。

关于您当前的问题。如果函数incrementLikes()incrementHearts()没有被调用,则这两个订阅肯定是undefined

答案 2 :(得分:0)

Sv En,如果你没有执行incrementLikes()或incrementHearts()你的变量没有重要价值。你可以做到

ngOnDestroy() {
    if (this.likeSub)  //if exist
      this.likeSub.unsubscribe();
    if (this.heartSub)  //if exist
    this.heartSub.unsubscribe();
  }

Filip,你不需要使用Subject,只需要一个布尔变量

this.dataService.editBlogPost(..)
   .takeWhile(() => this.isAlive)
   .subscribe(...)