2016-12-25 2 views
3

J'écris une application de bureau en utilisant angular2 et electron et il y a une fonctionnalité de téléchargement.Angular2 - Rxjs Sujet exécuté deux fois même après désabonnement

Mon DownloadService est ce

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 
     ... 
    } 
} 

Et mon ItemComponent est la suivante:

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

Le problème est quand je pause un élément Je me désabonne de Subject passé de DownloadService mais quand je reprends à nouveau, tous les console.log() imprime deux fois et ajoute deux fois les données à downloadedBytes. Aussi, si je fais une pause et recommence, Il va ajouter de plus en plus d'octets et de journaux!

J'ai cherché mais je n'ai pas trouvé d'indice à résoudre.

+1

Je pense que cela vient du fait que liste de téléchargement() ajoute le composant à une liste. Mais puisque nous ne savons pas à quoi sert cette liste, quand le sujet émet des événements, à quoi il sert, ce que fait la fonction pauseCourse(), etc., c'est difficile à expliquer. Fournir un exemple complet reproduisant le problème. –

+0

@JBNizet désolé j'ai fait beaucoup de simplification et apparemment le résultat n'était pas bon. J'ai ajouté plus de détails –

+1

Je ne peux pas le reproduire https://plnkr.co/edit/64mn6U1omy8JPE6LD4Nf?p=preview. Vérifiez également http://stackoverflow.com/questions/35673582/http-request-made-multiple-times-in-angular2-service – yurzui

Répondre

2

Vous pouvez voir la PLUNKER créé par yurzui que si vous reprendre et pause tout fonctionne comme prévu, une fois déclenchée que .
Le problème est lorsque vous cliquez sur CV 2 fois de suite comme premier abonnement sera perdu dans la mémoire et seule la seconde on sera stocké dans this.subscription l'accès au premier est perdu et vous ne pouvez pas vous désinscrire. Cela ressemble plus à un problème d'application que rxjs, vous ne devriez pas pouvoir cliquer sur reprendre si l'abonnement n'est pas suspendu, donc vous devez gérer les états correctement, quelque chose comme ceci (édité de @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; 
     }); 
    } 
} 

Vous pouvez trouver un exemple de travail dans cette mise à jour PLUNKER