Асинхронные вызовы в Angular 4 Pipes

У меня есть метод службы, который получает время с сервера, и я планирую использовать его в пользовательском канале. Цель конвейера — сравнить временную метку a с текущим временем и вернуть ее в удобочитаемом формате.

Сервис

export class TimeService{
  currentServerTime;

  fetchCurrentTimeStamp(){
     //http request using Observable
     return sendGETRequest(.....).map(data => {
        this.currentServerTime = data;

        return this.currentServerTime;
     })
  }
}

Канал

export class GetTimeFromNowPipe implements PipeTransform{

   fromNow;
   currentServerTime: number;
   constructor(private timeService: TimeService, private appSettings: AppSettings){}

   transform(value: number){
        var currentTime;
        this.timeService.fetchCurrentTimestamp().subscribe(data => {
            currentTime = data
            if(!value) return "";

            if(value){
               let newDate = moment.unix(value);
               this.fromNow = newDate.from(moment.unix(currentTime), true);
            }
          return this.fromNow;
        });

   }
}

HTML

<ul>
    <li *ngFor = "let model of models">
        <span>{{model.created | getTimeFromNow}}</span>
    </li>
</ul>

Я застрял с асинхронными вызовами. Как вернуть значение из канала только после получения данных с сервера?


person adityav    schedule 28.08.2017    source источник


Ответы (2)


return отсутствует, а subscribe необходимо изменить map, чтобы позволить асинхронному каналу выполнять подписку.

return this.timeService.fetchCurrentTimestamp().map(data => {

и для асинхронных значений необходимо использовать асинхронный канал

<span>{{model.created | getTimeFromNow | async }}</span>
person Günter Zöchbauer    schedule 28.08.2017

Лучший способ реализовать это — не использовать сервис внутри пайпа. Вы можете использовать пользовательский канал, чтобы реализовать только то, что должен делать канал. Ваша труба должна быть определена следующим образом:

export class GetTimeFromNowPipe implements PipeTransform{

   constructor(private appSettings: AppSettings){}

   transform(value: number, currentTime:number){
            if(!value) return "";
            else{
               let newDate = moment.unix(value);
               return newDate.from(moment.unix(currentTime), true);
            }
   }
}

внутри вашего компонента вы можете вызвать свою службу и сохранить ее внутри переменной в вашем жизненном цикле Oninit (конечно, вам нужно внедрить службу внутри компонента).

serverTime:number;
ngOnInit(){
  this.timeService.fetchCurrentTimestamp().subscribe(data=>this.serverTime=data);
    }

а затем внутри шаблона вашего компонента вы можете использовать свой канал. либо с

<ul *ngIf="serverTime">
    <li *ngFor = "let model of models">
        <span>{{model.created | getTimeFromNow:serverTime}}</span>
    </li>
</ul>

Or

<ul>
    <li *ngFor = "let model of models">
        <span>{{model.created | getTimeFromNow: serverTime | async}}</span>
    </li>
</ul>

Пояснение и цели:

цель этой реализации состоит в том, чтобы облегчить:

- Тестирование вашей трубы

-легкая отладка в случае, если у сервера есть проблемы

-независимая от сервера реализация, которую можно использовать в другом компоненте с другими параметрами (повторное использование).

person marouane kadiri    schedule 28.08.2017