2016-11-25 1 views
1

Je travaille actuellement sur une application Angular 2 mais j'ai quelques problèmes. En effet, j'ai une méthode qui obtient des données à partir d'une base de données. Cependant j'essaye de copier ces données à un autre, pour faire cela j'ai besoin de faire plusieurs demandes de HTTP (le nombre de demandes ne sont jamais les mêmes).Angular 2 - Demande HTTP multiple dans le même temps

Voici ma méthode migrate. D'abord, je reçois les données de DB puis je tente de les poster dans l'autre

service.getDatas().subscribe(data => { 
    let datas = data.json().data; 
    if (datas) { 
    let requests = []; 
    for (let data of datas) { 
     let req = service.addData(data); // addData() return an Observable 
     requests.push(req); 
    } 
    let c: Observable<any> = Observable.forkJoin(requests); 
    return c; 
    } 
}); 

Ou Quand je suis subribing à la méthode que je n'ai pas de réponse de celui-ci.

Voici mon abonné

service.migrateData(targetDB).subscribe(res => { 
     console.log(res); 
    }); 

Je veux que ma méthode pour retourner une réponse lorsque toutes les données ont été post! En fait, lorsque j'appelle la méthode addData(), elle ne déclenche même pas la requête http, rien ne se passe. J'ai essayé d'utiliser une méthode RxJs comme concat et forkJoin mais rien. Ou juste j'ai échoué à les utiliser.

Voici ma méthode addData()

addData(data) { 
    let headers = new Headers({ 
     'Content-Type': 'application/json' 
    }); 
    headers.append('Authorization', 'Basic ' + btoa('username + ':' + 'password)); 
    let _data = JSON.stringify({data: data}); 
    return this.http.post('https://something.com', _data, {headers: headers}); 
    } 

Cette méthode fonctionne très bien pour les autres cas utiliser.

Merci pour votre aide!

+0

Je pense que vous devez vous abonner à un observable avant qu'il ne soit exécuté. service.addData (données).abonnez-vous() –

+0

Si je fais cela, forkjoin aura un tableau d'abonnés et non un tableau observable: /! –

+0

Que diriez-vous de c.subscribe()? https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/forkjoin.md –

Répondre

0

Sur la base de votre code ce que je compris:

  1. obtenir quelques choix d'un service (d'un appel de repos)
  2. Faire un appel de repos pour chaque élément de ce tableau
  3. Obtenez un seul résultat à la fin quand tout est fait

const migrationStream$ = service.getDatas() 
    .map(data => data.json().data || [])  // and alternative to the "|| []" could be a subsequent ".filter(data => data && data.length)" 
    .switchMap(datas => Observable.from(datas)) // split up the js-array into a stream 
    .concatMap(data => service.addData(data)) 
    // .map(singleMigrateResponse => doSomethingWith(singleMigrateResponse)) // optional, is called for every data that is migrated 
    .toArray() // optional: this will wait for the previous part of the stream to complete and return an array of all results, remove this if you want to receive every result as a single "next" 

// run it by using: 
migrationStream$.subsribe(next..., error..., complete...); 

Cette méthode fonctionne très bien pour d'autres cas d'utilisation.

Comme une note genereal ici: rxjs peut être très poweful si elle est utilisée correctement, presque tout peut être écrit sous la forme d'un flux - en règle générale, vous pouvez rappeler à:

  • utiliser un seul abonnent par l'action (dans votre cas l'action est pas 1-3), si vous utilisez plus d'un abonnement, vous ne pensez pas dans les ruisseaux
  • essayer d'éviter logique de données dans l'abonnement, l'abonnement est préférable d'être utilisé pour la gestion des événements/émissions/résultats, par exemple migrationStream$.subscribe(..., ...,() => alert("Migration is complete!"));
0

Voici ma solution pour le flux multiples demandes avec 3 demandes parallèles

import {Component, OnInit} from '@angular/core'; 
import {HttpClient} from '@angular/common/http'; 

@Component({ 
    selector: 'app-multi-http', 
    template: `<ul> 
    <li *ngFor="let giphy of giphys"> <img src="{{giphy}}" width="200px"/> </li> 
    </ul>`, 
}) 
export class MultiHttpComponent implements OnInit { 
    // Requests stream vars 
    maxRequests = 3; 
    currentRequestsNbr = 0; 
    requestsStream = ['run', 'jump', 'hide', 'fight', 'surprise', 'sleep']; 

    giphys = []; 

    constructor(public http: HttpClient) { 
    } 

    ngOnInit() { 
     this.handleRequestsStream(); 
    } 


    handleRequestsStream() { 
     if (this.requestsStream.length > 0) { 
      if (this.currentRequestsNbr < this.maxRequests) { 
       ++this.currentRequestsNbr; 
       const searchTerm = this.requestsStream.shift(); 
       this.getGiphy(searchTerm).subscribe(
        url => { 
         this.giphys.push(url); 
        }, 
        error => { 
         console.log(error); 
        }, 
        () => { 
         --this.currentRequestsNbr; 
         // Try next request on complete 
         this.handleRequestsStream(); 
        } 
       ); 
       // Try next request 
       this.handleRequestsStream(); 
      } 
     } 
    } 

    getGiphy(searchTerm) { 
     const apiLink = '//api.giphy.com/v1/gifs/search?api_key=dc6zaTOxFJmzC&q=' + searchTerm; 
     return this.http.get(apiLink).map((response: any) => { 
      if (response.data.length > 0) { 
       return response.data[0].images.original.url; 
      } else { 
       return 'https://media.giphy.com/media/YaOxRsmrv9IeA/giphy.gif'; // dancing cat for 404 
      } 
     }); 
    } 
}