web-dev-qa-db-fra.com

Comment puis-je éviter plusieurs abonnements imbriqués à l'aide d'opérateurs RXJS?

Je travaille sur un cryptage de fichier et une classe de téléchargement en utilisant angulaire. Beaucoup de ces opérations sont asynchronisées et donc les méthodes que j'ai écrites sont des observables RXJS.

// 1.
private prepareUpload(file): Observable<T>;

// 2.
private encryptData(data, filekey): Observable<T>

// 3.
private uploadEncryptedData(formData, token, range): Observable<T>

// 4.
private completeUpload(updatedFilekey, token): Observable<T>

Je veux encapsuler cette logique dans un public upload(file) méthode et j'ai fini par utiliser des abonnements imbriqués et cela fonctionne, mais je sais que c'est faux et un anti-motif dans RxJS pour plusieurs raisons. Voici une version simplifiée du code:

public upload(file) {
    const gen = this.indexGenerator(); // generator function

    this.prepareUpload(file).subscribe(values => {
    const [response, filekey, data] = values;

    this.encryptData(data, filekey).subscribe(encryptedDataContainer => {
      const formData = this.prepareEncDataUpload(encryptedDataContainer.data, file.name)
      const range = this.getRange(file.size, gen.next().value);

      this.uploadEncryptedData(formData, response.token, range).subscribe(() => {
        if (range.isFinalPart) {
            this.completeUpload(encryptedDataContainer.updatedFilekey, response.token).subscribe(console.log);
        }
      });

    });

  });

}

J'ai échoué à nettoyer ce code à l'aide de combinaisons de plusieurs opérateurs RxJS. Mon objectif est d'éviter les abonnements imbriqués et de renvoyer plutôt un seul observable de la méthode du public upload() lorsque le flux de travail est terminé.

Merci!

9
Benny1158

Vous pouvez fusionner ces observables à l'aide de l'opérateur de mergemap RxJS et de vous débarrasser des abonnements imbriqués.

Bien qu'il y ait une capture, sachez que parce que Mergemap maintient plusieurs abonnements internes actifs à la fois, il est possible de créer une fuite de mémoire à travers des abonnements intérieurs de longue durée.

Pour référence et exemple: https://www.learnrxjs.io/opérators/transformation/mergemap.html

0
Sumit Vekariya

Je pense que la chaînage de vos observables le ferait, vous pouvez le faire avec Flatmap (alias pour mergemap) peut-être - https://stackoverflow.com/a/37777382/9176461 et RxJS Promise Composition (données de passage)

Comme dans mon commentaire mentint, quelque chose comme ce qui suit devrait fonctionner (pseudo code):

public upload(file) {
    const gen = this.indexGenerator(); // generator function

    return Rx.Observable.just(file).pipe(
         mergeMap(this.prepareUpload),
         mergeMap(this.encryptData),
         mergeMap(this.prepareEncDataUpload),
         mergeMap(this.prepareEncDataUpload),
         .... )
}
0
J. Knabenschuh