我有一个我无法解决的Angular 4问题。
我进行了几次http调用以获取数据。我所做的调用次数取决于先前的响应,其中包含要解决的项目列表。我需要进程 (concat响应)在将文件对象写入文件之前按顺序排列所有项目。问题是写入发生在调用完成之前。
ComponentA.ts:
this.service.getlist(parm1, parm2, parm3)
.finally( () => this.listComplete()
.map( lst => this.writeToFile(lst) )
.subscribe (res => { console.log("Done!"); } );
writeToFile(obj)
{
console.log("File Downloaded");
}
service.ts:
var response = this.http.post( this.sourceURL, options)
.map( res => { this.consumeList( res.json(), Objname ))
.finally( () => console.log(" I'm Done ")
.catch( (ex) => Observable.throw(this.reportError(ex)));
consumeList(obj : any, Objname)
{
obj.forEach( element => {
this.getChunk(obj);
}
)
}
getChunk(obj) {
this.http.get(obj,options)
.map(res => ths.getData(res, _name)
.catch( (ex) => Observable(this.logException(ex,_name)))
***.finally( () => this.clientWrite() )***
.subscribe();
}
getData(obj, name)
{
this._blob.push(obj);
}
clientWrite()
{
SaveAs([this._blob], _name);
}
在读取第一个对象后发生写入。
答案 0 :(得分:0)
因为我没有看到您使用的所有功能,所以我向您展示了如何使用Observable.forkJoin
的示例。 forkJoin
是同时执行多个http查询的最佳选择
<强>服务强>
getChunk(obj) {
//with help of this object you will inform Observable that everything has been done
let subject: Subject<any> = new Subject();
this.http.get(obj,options)
.map(res => ths.getData(res, _name)
.subscribe((element: any) => {
//if everything goes well
subject.next(element)
subject.complete();
}, (error: HttpErrorResponse) => {
//if you get error
subject.error(error);
subject.complete();
})
//remember to return this object
return subject;
}
在组件中,您使用getlist
,但在服务中没有此功能
getlist(objArray)
{
let obsArray = [];
objArray.forEach(element => {
//create Observable object and add them to array which you will return
obsArray.push(Observable.from(this.getChunk(element))
}
return obsArray;
}
在组件中使用
Observable.forkJoin(this.service.getlist([obj1, obj2, obj3]))
.subscribe(tArray => {
//tArray is array with response from all request
console.log("Done!");
}, error => {
})
记得在服务中导入
import { Observable, Subject } from 'rxjs';
和组件
import { Observable } from 'rxjs';
编辑 - 对评论的回应
如果没有看到整个代码,很难评估服务器返回的内容以及某些变量包含的内容。
<强> MyService.ts 强>
import { HttpErrorResponse, HttpClient } from '@angular/common/http';
import { Observable, Subject } from 'rxjs';
.... //others imports
@Injectable()
export class MyService {
private sourceURL: string = "http://youAPIAdress.com";
private _blob;
constructor(
private http: HttpClient
) {}
getChunkList(options: any, callback: (objURL: string[]) => void, errorCallback: (errorResponse: HttpErrorResponse) => void): void {
this.http.post( this.sourceURL, options)
.subscribe((objURL: any[]) => {
//if you use HttpClient don't have to do res.json()
//if objURL is not an array, make an array of received data
callback(objURL);
}, (error: HttpErrorResponse) => {
errorCallback(error)
})
}
getChunkElement(objURL) {
let subject: Subject<any> = new Subject();
this.http.get( objURL)
.subscribe((responseObj: any) => {
subject.next(responseObj)
subject.complete();
}, (error: HttpErrorResponse) => {
subject.error(error);
subject.complete();
})
return Observable.from(subject);
}
setData(chankElements: any[]): void {
//do somthing with recived part of the data
// this._blob.push(obj); - it will not work. I suggest using some library to work with blob object
//try this
this._blob = new Blob(chankElements, { type : 'image/jpeg' });
}
clientWrite(_name) {
//save data to local
SaveAs([this._blob], _name);
}
}
<强>组件强>
options: any;
constructor(
private myService: MyService,
) {
//set options
this.myService.getChunkList(this.options, response => {
//if response is adresses array
let obsArray = [];
response.forEach(urlAdress => {
obsArray.push(Observable.from(this.myService.getChunkElement(urlAdress))
})
Observable.forkJoin(obsArray)
.subscribe((chankElements: any[]) => {
//chankElements is array with response from all request
this.myService.setData(chankElements);
this.myService.clientWrite();
console.log("Done!");
}, error => {
//TODO somthing with error
})
}, error => {
//TODO somthing with error
})
}