1

I have the following in my controller, in a Spring-Boot application:

@RequestMapping(method=RequestMethod.GET,value="/info")
public DataModel getinfodata()
{
    //this method runs some script which takes more than 3 minutes and sends the response back
    return run_xyz()
}

In my angular app, I have this:

export class FetchService {
  private _url:string="/info";
    constructor(private _http:Http) { }
    getData():any
    {
      return this._http.get(this._url).map((res:Response)=>res.json()).
        catch(this.errorHandler).subscribe(data=>console.log(data));
    }
    errorHandler(error: Response){
      console.error(error);
      return Observable.throw(error || "Server Error");
    }

The issue I am facing currently is that the Http get is making silent retries to the server, and as result, my expensive script is getting called 3 or 4 times. Is there an approach by which the get will make only a single request with 0 retries and wait until the script is completed and then the response should be sent back.I am calling the getData method only once. Snapshot of response from backend Snapshot of Tomcat running on port 8080 Snapshot of server response in normal case, when the script is not running Angular CLI Final Response after 189 seconds

Vikas
  • 11,859
  • 7
  • 45
  • 69

2 Answers2

3

The http observable makes an http request for each subscriber. So the 3 to 4 http request means you must have multiple components subscribing at the same time. To share a single http request for multiple observers, you need something like the share operator.

export class FetchService {
    data$: Observable<any>;

    constructor(){
        this.data$ = this._http.request(this._url)
            .map((res:Response)=>res.json())
            .catch(this.errorHandler)
            .share();
    }

    getData(){
        return this.data$;
    }
}

Now the multiple observers will share the same observable.

This operator is a specialization of publish which creates a subscription when the number of observers goes from zero to one, then shares that subscription with all subsequent observers until the number of observers returns to zero, at which point the subscription is disposed.


As for your ERR_EMPTY_RESPONSE issue. I've run into this when my proxied api call timesout.

LLai
  • 13,128
  • 3
  • 41
  • 45
  • I am subscribing it only once not multiple time, the issue is with get request if the response is not being sent from the server within 120(as observed) seconds it is making another request. – Vikas Dec 29 '17 at 03:38
  • 1
    @VikasSingh you are using the webpack dev server proxy? – LLai Dec 29 '17 at 15:28
  • nope I am using node.js and tomcat and to be honest I haven't heard the term webpack dev server proxy – Vikas Dec 29 '17 at 15:51
  • @VikasSingh from your image, I was assuming you were running angular cli with `ng serve` since the image shows localhost:4200 – LLai Dec 29 '17 at 15:56
  • @VikasSingh really `ng serve` should only be used for development. When using `ng serve` you will have to proxy your api requests if they are on the same domain as your app. So your app is making api request to localhost:4200 (app hosted by ng serve), but the api is hosted on localhost:3000 (assuming you are using the default node js port). So you need to proxy api request from localhost:4200 to localhost:3000. Here are the [docs](https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md) from angular cli on using a proxy config – LLai Dec 29 '17 at 16:02
  • But Tomcat server is up and running on port:8080 and I have configured it in proxy-config.json. – Vikas Dec 29 '17 at 16:11
  • @VikasSingh I'm not too familiar with TomCat. It sounds like you need to use `ng build` to build your app in the appropriate directory within TomCat. – LLai Dec 29 '17 at 16:15
  • For your reference, I have added few snapshots, I get the correct response in normal cases but not when script starts running it takes a lot of time and result is always ERR_EMPTY_RESPONSE – Vikas Dec 29 '17 at 16:33
  • I got some other information,[link](https://stackoverflow.com/questions/tagged/keep-alive) because of this feature of HTTP if client is not getting response from server in stipulated time, it is making another request and until timeout @LLai – Vikas Dec 29 '17 at 16:57
  • @Vikas what address do you hit to view your angular app? – LLai Dec 29 '17 at 17:00
  • @Vikas should you not be using `ng build` to build your static app files and placing them within tomcat? ([SO question](https://stackoverflow.com/questions/37933313/how-do-i-deploy-an-angular2-app-on-a-local-tomcat-server)) `ng serve` spins up a webpack dev server to serve your application on localhost:4200. – LLai Dec 29 '17 at 17:07
  • No man currently I am Consuming a RESTful Web Service with Angular, why do I need to deploy it to tomcat [check this link](https://oliverveits.wordpress.com/2017/06/24/consuming-a-restful-web-service-with-angular-4/) @LLai – Vikas Dec 29 '17 at 17:19
0

Eventually, I figured out why it is happening The dev-server makes use http-proxy-middleware package More Here and the proxy options provided in this package is from underlying http-proxy library http-proxy options. one among them is

proxyTimeout:

timeout (in millis) when the proxy receives no response

The default value is ~120 seconds(based on my observations) if the server fails to respond within the stipulated time(120s) a new request is made to the server. overriding the default timeout with "timeout":30000 in proxy config file resolved the issue.

{
  "/info": {
     "target":  {
       "host": "localhost",
       "protocol": "http:",
       "port": 8080
     },
     "secure": false,
     "changeOrigin": true,
     "logLevel": "debug",
     "timeout":30000
  
  }
}
Community
  • 1
  • 1
Vikas
  • 11,859
  • 7
  • 45
  • 69