Почему асинхронный конвейер angular 11 не стабилизируется с помощью наблюдаемого с задержкой?

Я подписываюсь на отложенное наблюдаемое через асинхронный канал в angular 11.

По какой-то причине обнаружение изменений (?) Не стабилизируется, и канал не получает значения, и я не могу понять, почему? ???? Вместо отображения моих данных отображается null.

пример: https://stackblitz.com/edit/angular-async-pipe-with-delay?devtoolsheight=33&file=src/app/app.component.html

html

<h1>{{ getData(0) | async | json }}</h1>

составная часть

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private dataService: DataService) {}
  getData(id: number) {
    return this.dataService.getDataDelayed(id).pipe(tap(console.log));
  }
}

услуга


const data = [
  {
    id: 0,
    data: 'hello'
  }
];

@Injectable()
export class DataService {
  constructor() {}

  getDataDelayed(id: number) {
    return of(data[id]).pipe(delay(5000)); // works fine without the delay
  }
}

person Markus    schedule 07.06.2021    source источник
comment
обнаружение изменений (?) не стабилизируется - это хорошо известное поведение, когда функции связываются в директивах или вызываются при интерполяции. См. Здесь: stackoverflow.com/a/66707617/6513921   -  person Michael D    schedule 07.06.2021
comment
то же самое и с onPush. Однако я все равно ожидаю, что мои ценности будут показаны. Я также хочу использовать асинхронный канал без подписок на компоненты. Ничто другое не вызывает changeDetection и без задержки стабилизируется.   -  person Markus    schedule 07.06.2021
comment
Проблема заключается в следующем: в момент, когда служба возвращает данные, запускается новый цикл обнаружения изменений. Это приводит к повторному вызову вашего метода getDataDelayed(). В этот момент наблюдаемое замещается новым (потому что запускается новый запрос), который еще не имеет значения и поэтому отображается как null.   -  person JSON Derulo    schedule 07.06.2021
comment
@Markus: Проблема в задержке вызова функции. См. Здесь: stackblitz.com/edit/   -  person Michael D    schedule 07.06.2021
comment
@MichaelD вы устранили необходимость вызова функции, убрав возможность проходить через id. это, конечно, обходит проблему :)   -  person Markus    schedule 07.06.2021
comment
вот более реальный пример того, что я пытаюсь сделать: stackblitz.com/edit/   -  person Markus    schedule 07.06.2021


Ответы (1)


Вам нужно быть осторожным, когда вы используете асинхронный канал для вызова функции. Асинхронный конвейер хранит ссылку на наблюдаемое и подписывается на него. Когда вы используете вызов функции getData, новый наблюдаемый объект создается каждый раз, когда происходит обнаружение изменений, и поэтому асинхронный канал подписывается на новый наблюдаемый объект и больше не ждет предыдущего.

Что вы можете сделать, изменив метод getData, чтобы сохранить ссылку на наблюдаемое, чтобы он всегда возвращал одно и то же наблюдаемое для данного идентификатора.

  private data: Observable<any>[] = [];

  getData(id: number) {
    if (!this.data[id]) {
      this.data[id] = this.dataService
        .getDataDelayed(id)
        .pipe(tap(console.log));
    }
    return this.data[id];
  }
person J.Loscos    schedule 07.06.2021