3

I understand the Async pipe works on observable and help us load thing async for data which will be coming later.

However I can work without using async too. Following is the code

Component

export class XComponent{
     someProp: string;
     someList: string[];
     someFn(){
          this.someService.subscribe(
               data=>{
                    this.someProp = data.prop; 
                    this.someList = data.list;
               }
          );
     }
}

Template

.....

<label>Prop</label>
<span>{{someProp}}</span>
<label>List</label>
<span *ngFor="let item of someList">{{item}}</span>

Above code works for me without use of async and without any issue. They why should I use async? Is it because we don't need to declare a variable for data and we can use directly observable (We anyways needs to declare a observable instead of data though)?

EDIT

Following is the code taken from angular docs for async example

@Component({
  selector: 'async-observable-pipe',
  template: '<div><code>observable|async</code>: Time: {{ time | async }}</div>'
})
export class AsyncObservablePipeComponent {
  time = new Observable<string>((observer: Subscriber<string>) => {
    setInterval(() => observer.next(new Date().toString()), 1000);
  });
}

Instead of that I can write

@Component({
  selector: 'async-observable-pipe',
  template: '<div><code>observable|async</code>: Time: {{ time }}</div>'
})
export class AsyncObservablePipeComponent {
  time;
  constructor(){
    setInterval(() => time = new Date().toString(), 1000); 
  } 
}

To me second code looks clean too. (Even cleaner)

Akshay
  • 3,558
  • 4
  • 43
  • 77
  • 3
    The async pipe is to avoid the subscriptions inside the. The behaviour of async pipe is that it'll subscribe your observer return the data into your loop variable and then unsubscribe that observer automatically. – Babar Hussain Mar 23 '17 at 09:21
  • @BabarBilal The AsyncPipe does not unsubscribe until the component is destroyed. This is documented in the Angular AsyncPipe docs. – Mantas Mar 23 '17 at 09:24
  • Yeah but you dont need to manually destroy it in ngOnDestroy – Babar Hussain Mar 23 '17 at 09:25
  • We don't need to manually destroy any observable which was attached to component. Angular automatically does that. – Akshay Mar 23 '17 at 09:39
  • 2
    @Akshay : That's not true. For some special cases you need to unsubscribe yourself. See this : http://stackoverflow.com/questions/38008334/angular2-rxjs-when-should-i-unsubscribe-from-subscription – Alex Beugnet Mar 23 '17 at 09:55
  • Question essentially boils down to : Why should I write fully reactive code ? Well, maintainability, readability, state management. Ofc you can do it in a non async way, but in the long run it is just harder to manage. – Standaa - Remember Monica Mar 28 '19 at 12:36

3 Answers3

2

What: With AsyncPipe we can use promises and observables directly in our template, without having to store the result on an intermediate property or variable

Why :Normally to render result of promise or observable we have to do

  1. Wait for a callback.

  2. Store the result of the callback is a variable.

  3. Bind to that variable in the template.

async makes rendering data easier from promises and observables. Suppose if we use observables without async, we have to subscribe the data from observable and we need to unsubscribe that on ngdestroy hook to avoid memory leaks.but where as with async will take care of this automatically.

"The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted. When a new value is emitted, the async pipe marks the component to be checked for changes"

How

`@Component( 
{

selector: 'async-observ',

  template: `
 <div>
  <h5>Async demo</h5>
  <p>{{ observable | async }}</p> 
 </div>
})

class AsyncObservComponent {

    observable: Observable<number>;

    constructor() {

     this.observable = this.getObservable();

   }

  getObservable() {

    return Observable
      .interval(1000)
      .take(5)
      .map((v) => v*v)
   }
pa1 Raju
  • 153
  • 1
  • 7
1

The main reason is because using an async pipe, your code will be much cleaner.

Imagine a case where the data returned consists of tens or hundreds of keys instead of two. It would be too cumbersome to set all the inner variables.

As an addition, according to the Angular docs, the AsyncPipe will only take the last value omitted by the observable (which is the perfect solution to show a value in the view). If you keep trace of the observable itself in the XComponent, you are then capable of getting all of the values, first values and do all sorts of data manipulation.

EDIT: To support the new example you gave:

time = Observable.interval(1000).flatMap(() => new Date().toString());
Mantas
  • 89
  • 6
  • He is asking about async functionality – Babar Hussain Mar 23 '17 at 09:19
  • I can create a template without async and using only one variable for thousand keys. If you don't agree to me than please give me an example. – Akshay Mar 23 '17 at 09:21
  • @Akshay yes, you can do that if that is more convenient and there is nothing wrong with such an approach. However, if you need previously emitted data (other than the last), or, for example, only allow some values to pass based on custom logic, you need the observable rather than just reassigning values in subscription inside of the class. It simply allows more flexibility for data manipulation rather than simply taking the last value. – Mantas Mar 23 '17 at 09:26
1

You have to subscribe to observables to return their data. Instead of subscribing manually, you can use the async pipe in your HTML file. This will subscribe to the observable, return dynamic values, and unsubscribe the observable on component changes.

@Component({
  selector: 'async-observable-pipe',
  template: '<div><code>observable|async</code>: Time: {{ time | async }}</div>'
})
export class AsyncObservablePipeComponent {
  time = new Observable<string>((observer: Subscriber<string>) => {
    setInterval(() => observer.next(new Date().toString()), 1000);
  });
}
ANKIT MISHRA
  • 558
  • 4
  • 13