处理多个http请求并在Angular 4结束时订阅

时间:2018-03-08 20:49:43

标签: angular synchronous subscription

我有一个我无法解决的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);

}   

在读取第一个对象后发生写入。

1 个答案:

答案 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
    })
  }