4

I trying to set Pipe in angular 6 that convert text to other with using service (the method that returns observable)

I tried the following code, but I need to return a string instead of Promise

Pipe:

import { Pipe, PipeTransform } from '@angular/core';
import { TimeZoneService, TimeZone } from '../services/Global/timezone.service';
//import { resolve } from 'dns';
import { reject } from 'q';
import { Observable } from 'rxjs';

@Pipe({
  name: 'utcToText'
})
export class UtcToTextPipe implements PipeTransform {

  private timezoneLst: TimeZone[] = [];

  constructor(private _timezoneSvc : TimeZoneService) {}

  async transform(timezone: any, args?: any){
    this.timezoneLst = await this._timezoneSvc.getTimeZonesLst().toPromise();
     return this.timezoneLst.find(x => x.utc.indexOf(timezone) > -1).text;

}
}

html:

<span>{{subscription.time_zone |  utcToText}</span>

There is any way to make the asynchronous method of Promise / Ovservabe to a synchronous function that returns synchronous such as String?

Thanks a lot for helpers.

Ran Alcobi
  • 189
  • 1
  • 2
  • 11
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Igor Jan 10 '19 at 17:42
  • No, I want to return string instead of Promise – Ran Alcobi Jan 10 '19 at 17:57
  • You don't need to return a string, you can return `Promise` or `Observable` and chain the `async` pipe to resolve the value. See the provided answer. – Alexander Staroselsky Jan 10 '19 at 17:59

1 Answers1

24

Try instead returning an Observable<string> and chaining the async onto your existing pipe. Also you simply will not be able to return string with the async nature of your API calls.

Pipe:

import { Pipe, PipeTransform } from '@angular/core';
import { TimeZoneService, TimeZone } from '../services/Global/timezone.service';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Pipe({ name: 'utcToText'})
export class UtcToTextPipe implements PipeTransform {
  constructor(private _timezoneSvc : TimeZoneService) {}

  transform(timezone: string, args?: any): Observable<string> {
    // this assumes getTimeZonesLst() returns an Observable<TimeZone[]>
    return this._timezoneSvc.getTimeZonesLst().pipe(
      map((timeZones: TimeZone[]) => {
        return timeZones.find(x => x.utc.indexOf(timezone) > -1).text;
      })
    );
  }
}

Template:

<span>{{subscription.time_zone | utcToText | async}</span>

Here is a example async pipe in action derived from the exponential pipe example in the Angular documentation.

If you really need to use promises instead of observables for some reason:

import { Pipe, PipeTransform } from '@angular/core';
import { TimeZoneService, TimeZone } from '../services/Global/timezone.service';
import { Observable } from 'rxjs';

@Pipe({ name: 'utcToText'})
export class UtcToTextPipe implements PipeTransform {
  constructor(private _timezoneSvc : TimeZoneService) {}

  transform(timezone: string, args?: any): Promise<string> {
    // this assumes getTimeZonesLst() returns an Observable<TimeZone[]>
    return this._timezoneSvc.getTimeZonesLst()
      .toPromise()
      .then((timeZones: TimeZone[]) => {
        return timeZones.find(x => x.utc.indexOf(timezone) > -1).text;
      })
  }
}

Hopefully that helps!

Alexander Staroselsky
  • 37,209
  • 15
  • 79
  • 91
  • You are the BEST! Thanks a lot!! – Ran Alcobi Jan 10 '19 at 18:19
  • i was returning an observable with no luck. after converting it to a promise this worked great. i am not sure why promise works over an observable when using an async pipe. – Phil Ninan Mar 27 '20 at 21:13
  • @PhilNinan You would need to share what your code looks like. You can return an observable, but there may be an issue with how you are returning. For example if you have `subscribe()` anywhere in the observable you are returning, then you aren't returning the actual observable. Hard to say without seeing your exact code. – Alexander Staroselsky Mar 27 '20 at 21:23
  • ah that was my problem i was calling subscribe. return this.service.getEvent(value).toPromise().then(res => { return res.description; }); vs return this.service.getEvent(value).subscribe(res => { return res.description; }); – Phil Ninan Mar 27 '20 at 21:42
  • why does calling subscribe cause problems? – Phil Ninan Mar 27 '20 at 21:47
  • 1
    @PhilNinan Return type of `subscribe()` is not `Observable`. It's not an observable, but a [subscription](https://rxjs-dev.firebaseapp.com/guide/subscription). As overall rule, never try to return anything from within a `subscribe()` either, it won't actually return anything. – Alexander Staroselsky Mar 27 '20 at 21:50