0

Http calls are made twice in angular universal on the initial load,I tried applying transferstate and also done the caching mechanism in my project,still nothing happens.

if (isPlatformBrowser(this.platformId)) {
 return this.http.get(baseApi + '/blog/slug/' + blogId);
} else {
  const store = this.state.get(MY_DATA, null);
  if (store) {
    return store;
  }
  const myData = this.http.get(baseApi + '/blog/slug/' + blogId);
  this.state.set(MY_DATA, myData);
  return myData;
}

Network Calls Screenshot enter image description here

Am i missing something or is there anything that i have to include inorder to avoid browser calls that are made? Thanks in Advance.

gautam siva
  • 103
  • 2
  • 11
  • You can only cache data with state transfer. It looks like you are trying to cache an observable. And your first if is wrong, it means that you'll always make the http call client side – David Mar 04 '20 at 20:58
  • The real problem is , angular ssr calls api's twice on initial load from browser and server.Here i have to restrict the browser calls,so from my recent research i found out that using this way we can restrict the browser calls.But nothing works and still the call is made twice.Is there any solution for this as issue is still open in Github? – gautam siva Mar 05 '20 at 04:37
  • Provide data on the networks calls made. Use your browser dev-tools, go to Networks tab, make a screenshot of the calls. Add the screenshot to the question. – 0leg Mar 05 '20 at 08:15
  • In my network, i can see an additional api call that is made.So here one api call is made by server and the other one client,Attached network calls screenshot as well – gautam siva Mar 06 '20 at 04:48

3 Answers3

1

if your condition is verified it executes the query

if (isPlatformBrowser(this.platformId)) {
  return this.http.get(baseApi + '/blog/slug/' + blogId);
 } 

in the contrary case the it enters in the else one except that

const myData = this.http.get(baseApi + '/blog/slug/' + blogId);
  this.state.set(MY_DATA, myData);
  return myData;

is always executed regardless of the test performed.

christ_dev
  • 21
  • 1
  • But still the calls are made twice initially whenever the page hits the browser,do i have to use any interceptor file to restrict globally? – gautam siva Mar 05 '20 at 04:38
0

Like I said in my comment, you can only cache data with state transfer. From your code, it looks like you are trying to cache an observable. And your first if is wrong, it means that you'll always make the http call client side

To avoid making calls twice, you can use something like the code below, that will also prevent to call to be made twice server side

//Check if cached version exists
const data = this.state.get(MY_DATA, null);
if (data) 
{
    return of(data); //data exists
}

//Data has not been cached yet. Make the call and store result

return this.http.get(baseApi + '/blog/slug/' + blogId)
.pipe(tap(res=> {this.state.set(MY_DATA, res);} );

You could also use a more the TransferStateHttpCacheModule, which provides a generic interceptor that does it for all your requests

David
  • 33,444
  • 11
  • 80
  • 118
-1

fixed the issue by installing preboot,For the people who are having the same issue, you can follow this: we need to wait for the full client app to bootstrap and run or buffer events using librabries like preboot.

npm i preboot

add below code under imports of app.module.ts

PrebootModule.withConfig({ appRoot: 'app-root' })

Also add the below code to your providers in app.module.ts if necessary,

{
provide: APP_INITIALIZER,
  useFactory: function(document: HTMLDocument, platformId: Object): Function {
    return () => {
      if (isPlatformBrowser(platformId)) {
        const dom = ɵgetDOM();
        const styles: any[] = Array.prototype.slice.apply(dom.querySelectorAll(document, `style[ng-transition]`));
        styles.forEach(el => {
          // Remove ng-transition attribute to prevent Angular appInitializerFactory
          // to remove server styles before preboot complete
          el.removeAttribute('ng-transition');
        });
        document.addEventListener('PrebootComplete', () => {
          // After preboot complete, remove the server scripts
          setTimeout(() => styles.forEach(el => dom.remove(el)));
        });
      }
    };
  },
  deps: [DOCUMENT, PLATFORM_ID],
  multi: true  
}

And after adding these, for me the flickering issue was resolved.

Refer the official angular ssr link for more clarity : https://angular.io/guide/universal

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
gautam siva
  • 103
  • 2
  • 11