0

I've been digging an issue with Angular 4 and RxJS. Here is my code, the issue is, the http.post request Observable is not emitting anything to the next of the chain, the map(). The POST just get an endless response, it's a stream of Motion JPEG data. Now I have to deal with the data, say each 500KB transferred. My problem is that I cannot do anything with the data if the Observable not emitting anything.

So how to make such angular HTTP feature emit to the next of the chain each chunk of data transferred?

postActionGivenDataBinaryResponse(url:string, data:string) : Observable<any>{
    let headers = new Headers ({
        'Content-Type' : 'application/json;charset=utf-8'
    }) ;
    let options = new RequestOptions({
        headers : headers,
        responseType: ResponseContentType.ArrayBuffer
    }) ;

    //return binary data as is no json
    return this.http.post(url, data, options) //suspecting here is not emitting anything due to unknown configuration issue.
                    .map(this.extractBinaryData)
                    .catch(this.handleError) ;
}

private extractBinaryData(res:Response){
    console.log('Dealing with data in the com service.') ; // this never runs
    return res ;
}

I call the above function like this, the post response is an endless binary data, I need to process it as string array.

this.mySubscription = this.comService.postActionGivenDataBinaryResponse(myurl,mydata)
  .do(()=>{
              console.log('Observable Passed data.') ; //this never runs.
          })
  .bufferCount(128000)
  .map((data)=>{//process the data each 128kb chunk})
  .subscribe();
tomriddle_1234
  • 3,145
  • 6
  • 41
  • 71
  • I don't get what the question is about. Where do you call `postActionGivenDataBinaryResponse`? Where do you expect a value but don't get one? – Günter Zöchbauer May 21 '17 at 07:43
  • @GünterZöchbauer, I commented my code for the issue. That function is just a POST. I expect the data would be emitted by chunk, but it never emits now, but debug shows the data is transferred no problem. Need to know why. – tomriddle_1234 May 21 '17 at 07:51
  • @tomriddle_1234 where did you see in the documentation that the Angular Http.post method returned an Observable emitting an event for every byte received in the response? Why do you make that assumption? – JB Nizet May 21 '17 at 07:59
  • @JBNizet, I would like to know how to solve my situation, are you saying I shouldn't use Angular's HTTP module? I just need http emit event each chunk of data recieved. How? – tomriddle_1234 May 21 '17 at 08:06
  • I have no clear idea. But if it's possible, my guess is that you'll have to use a lower-level mechanism, using XMLHttpRequest directly. – JB Nizet May 21 '17 at 08:20
  • @JBNizet, after some digging, I found this, https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data, and this, http://stackoverflow.com/a/33042003/921082, however is there any update ? – tomriddle_1234 May 21 '17 at 09:35

2 Answers2

0

I am assuming you are seeing the response sent from the server on the network tab but its got getting out from the map operator. I am just guessing the problem could be in how you have used the function extractBinaryData() inside the map. Instead, could you just not use the function and just do a .map(res => res) or remove that.. I am assuming the "this" reference inside the map is not the object that holds the extractBinaryData() method. Please try this and let us know if it solved the issue.

Sundar
  • 41
  • 7
  • I don't think so, as I dig it through, it appears Angular till version 4.x, still doesn't support endless stream for its HTTP module. – tomriddle_1234 May 21 '17 at 16:13
0

I solved this issue by a trick that MDN provided. It's about how to transfer binary data

So I wrote my own request instead of using Angular's HTTP module.

And utilizing the responseText trick to keep the request never ending.

The request is like,

function load_binary_resource(url) {
  var req = new XMLHttpRequest();
  req.open('GET', url, false);
  //XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
  req.overrideMimeType('text\/plain; charset=x-user-defined');
  req.send(null);
  if (req.status != 200) return '';
  return req.responseText;
}

I just need to wrap this into an observable, then data would keep streaming and never stop unless the request is abort().

tomriddle_1234
  • 3,145
  • 6
  • 41
  • 71