0

In Angular 2+, with async pipe, I'm wondering why the call of a function returning a promise only do an infinite loop and crash eventually.

  1. Why cannot we call a function returning a promise directly from the template of a component in the case of an async task?

Without that, we absolutely have to have properties declared within the component for each time we want to do an async job.

In the following example, it's the case of the property "Articles" which will be used to retrieve the data of the Promise, and it will work.

However doing a "shortcut" by using the function returning a promise will simply fail and eat all memory (tested on chrome, and on nodejs).

  1. Why this behaviour is occuring?

This is a full example (be careful, it will crash your browser if you try it):

import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    <div>
      <p>CASE THAT WORKS PERFECTLY</p>
      Getting value from an indirect call:
      {{Articles|async}}
    </div>

    <div>
      <p>CASE THAT WILL CRASH YOUR BROWSER (memory eater)</p>
      Getting value from a direct call to the function returning the Promise-string :
      {{simulateDb()|async}}
    </div>
  `,
})
export class App {

  Articles:string;

  constructor() {
   this.Articles = (  this.simulateDb());       
  }

  simulateDb()
  {
    return new Promise((a,b)=>{ 
         a('this is a result');
     });
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App  ],
  providers: [  

  ],
  bootstrap: [ App ]
})
export class AppModule {}
Micaël Félix
  • 2,697
  • 5
  • 34
  • 46
  • 2
    Because the second one calls the function every time it needs to update the display, creating a new promise each time, and the first one calls it once? Possible duplicate of https://stackoverflow.com/questions/36700648/angular-2-binding-to-a-function-on-the-view-results-to-infinite-calls-to-the-dat – jonrsharpe Oct 29 '17 at 18:05
  • OK I understand, so there's nothing I can do except storing a single reference in the object? Is there any possibility to ask Angular to never refresh that part once the first call has been made? – Micaël Félix Oct 29 '17 at 18:38
  • You could take over change detection manually, but then why use Angular? What's the *problem* with getting a single promise then resolving it with the AsyncPipe? – jonrsharpe Oct 29 '17 at 18:40
  • Well the "problem" is that you have to create a property to store a promise given by a function, and use that property in the template. I would find it way easier to use directly the function in the template. Why bother declaring a property if it's for a "one time" use and a direct call to a function would work? I have a case where I need that 5 times, so the solution (I'd call it "compromise") was to put all reference of promises in an object property that I would call directly from the template. – Micaël Félix Oct 29 '17 at 19:20
  • 1
    You mean other than that it *doesn't* work, as demonstrated by your example for the reason I outlined, which is why you're asking? Calling it once in the constructor *is* how you tell Angular not to call it again; if you call it from the template, Angular has to keep calling to find out if it's changed. – jonrsharpe Oct 29 '17 at 19:29
  • Hmmm OK, my bad then, I forgot that point. Thank you! – Micaël Félix Oct 29 '17 at 19:36

0 Answers0