Angular2 - 即使在取消订阅后,Rxjs Subject 运行 两次
Angular2 - Rxjs Subject run twice even after unsubscribing
我正在使用 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;
});
}
}
问题是当我暂停从 DownloadService
传递的 Subject
取消订阅的项目时,但是当我再次恢复时,每个 console.log()
打印两次并向 [=18 添加两次数据=].
另外,如果我暂停并再次恢复,它会添加越来越多的字节和日志!
我搜索过,但找不到解决问题的线索。
您可以从 PLUNKER created by yurzui 中看到,如果您 resume 和 pause 一切正常,仅触发 一次。
问题是当您连续点击 恢复 2 次 时,第一个 订阅将在内存中丢失,只有second 一个将存储在 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
中找到一个工作示例
我正在使用 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;
});
}
}
问题是当我暂停从 DownloadService
传递的 Subject
取消订阅的项目时,但是当我再次恢复时,每个 console.log()
打印两次并向 [=18 添加两次数据=].
另外,如果我暂停并再次恢复,它会添加越来越多的字节和日志!
我搜索过,但找不到解决问题的线索。
您可以从 PLUNKER created by yurzui 中看到,如果您 resume 和 pause 一切正常,仅触发 一次。
问题是当您连续点击 恢复 2 次 时,第一个 订阅将在内存中丢失,只有second 一个将存储在 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
中找到一个工作示例