问题
I'm actually working on an Angular 2 application but i have a some problems. Indeed, i have a method which get data from a database. However i'm trying to copy this data to an other one, to do that i need to do multiple HTTP request ( the requests number are never the same ).
Here is my migrate method. First I get the data from DB and then I try to post them in the other one
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;
}
});
Or When i'm subribing to the method i have no Response from it.
Here is my subscriber
service.migrateData(targetDB).subscribe(res => {
console.log(res);
});
I want my method to return a Response when all the data has been post ! Actually when i'm calling the addData() method it doesn't even trigger the http request, nothing happens. I tryed to use some RxJs method like concat and forkJoin but nothing. Or just i failed using them.
Here is my addData() method
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});
}
This method works very well for others use case.
Thanks for your help !
回答1:
Based on your code this is what I understood:
- Get some array from a service (from a rest call)
- Make a rest call for every element in that array
- Get a single result in the end when everything is done
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...);
This method works very well for others use case.
As a genereal note here: rxjs can be very poweful if used properly, almost everything can be written as a stream - as a rule of thumb you can remember to:
- only use one subscribe per action (in your case the action is steps 1-3), if you are using more than one subscribe, you're not thinking in streams
- try to avoid data-logic within the subscription, the subscription is best to be used for handling events/emits/results, e.g.
migrationStream$.subscribe(..., ..., () => alert("Migration is complete!"));
回答2:
Here is my solution for multiple requests stream with 3 parallel requests
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
}
});
}
}
来源:https://stackoverflow.com/questions/40807725/angular-2-multiple-http-request-in-the-same-time