【问题标题】:Angular2 - Rxjs Subject run twice even after unsubscribingAngular2 - 即使在取消订阅后,Rxjs 主题也会运行两次
【发布时间】:2016-12-25 07:12:51
【问题描述】:

我正在使用 angular2 和 electron 编写一个桌面应用程序,并且有下载功能。

我的DownloadService是这个

import {Injectable} from '@angular/core';
import {Subject} from "rxjs";

interface IQueueItem {
    url: string
}

@Injectable()
export class DownloadService {
    private queue: Array< IQueueItem > = [];

    private downloadSubject: Subject<any>;

    constructor() {
        this.downloadSubject = new Subject();
    }

    addToList(item: IQueueItem) {
        this.queue.unshift(item);

        downloadList();

        return this.downloadSubject;
    }

    downloadList() {
        // pick one item from queue and send it to electron to download and store

        // do this every time a chunk of data received
        this.downloadSubject.next(evt);
        ...
    }

    pauseDownload(item) {
        // send an event to electron to it should stop downloading and therefore no chunk of data will receive
        // also remove item from queue
        ...
    }
}

而我的ItemComponent 是这样的:

import {Component} from '@angular/core';
import {DownloadService} from "../services/download.service";

@Component({
    selector: 'app-item',
    template: `
        ...
      `
})
export class ItemComponent {
    constructor(private downloadService: DownloadService) {
        this.addToQueue();
    }

    subscription;

    downloadedBytes = 0;

    fileUrl = '';

    pause() {
        this.downloadService.pauseDownload(this.fileUrl);

        this.subscription.unsubscribe();

        ...
    }

    resume() {
        this.addToQueue();
    }

    private addToQueue() {
        this.subscription = this.downloadService.addToList(this.fileUrl)
            .subscribe(evt => {

                console.log(evt.delta);

                this.downloadedBytes += evt.delta;
            });
    }
}

问题是当我暂停从Subject 取消订阅的项目时,从DownloadService 传递但当我再次恢复时,每个console.log() 打印两次并向downloadedBytes 添加两次数据。 此外,如果我再次暂停和恢复,它会添加越来越多的字节和日志!

我搜索了但我找不到任何线索来解决。

【问题讨论】:

  • 我的猜测是它来自于 downloadList() 将组件添加到列表中的事实。但是由于我们不知道这个列表是干什么用的,主体什么时候发出事件,它是干什么用的,pauseCourse() 做了什么等等,就很难解释了。提供重现问题的完整示例。
  • @JBNizet 对不起,我做了很多简化,显然结果并不好。我添加了更多细节

标签: angular rxjs subject-observer


【解决方案1】:

您可以从yurzui 创建的PLUNKER 中看到,如果您恢复暂停 一切都按预期工作,仅触发一次
问题是,当您连续点击 2 次恢复,因为 第一个 订阅将丢失在内存中,只有 第二个一个将存储在 this.subscription 中,对第一个的访问将丢失,您无法取消订阅。

这更像是一个应用程序问题而不是 rxjs,如果订阅没有暂停,您应该无法单击恢复,因此您需要正确处理状态,如下所示(编辑自 @yurzui plunker):

@Component({
  selector: 'my-app',
  template: `
    <h1>Angular 2 Systemjs start</h1>
    <button *ngIf="started && !paused" (click)="pause()">Pause</button>
    <button *ngIf="started && paused" (click)="resume()">Resume</button>
    <button *ngIf="!started" (click)="start()">Start</button>
  `
})
export class App {
  constructor(private downloadService: DownloadService) {
    this.addToQueue();
  }

  subscription;
  downloadedBytes = 0;
  started = false;
  paused = false;


  pause() {
    this.paused = true;  

    this.subscription.unsubscribe();
  }

  start() {
    this.started = true;  

    this.addToQueue();
  }

  resume() {
    this.paused = false;

    this.addToQueue();
  }

  private addToQueue() {
    this.subscription = this.downloadService.addToList(this)
      .subscribe(evt => {

        console.log(11);

        this.downloadedBytes += evt.delta;
      });
  }
}

您可以在更新后的PLUNKER 中找到一个工作示例

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-30
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多