Показывать анимацию загрузки при получении данных (Angular 10)

Я пытаюсь показать анимацию загрузки в Angular 10, пока я извлекаю данные. Я могу показать анимацию загрузки, если использую определенное значение времени, но я не могу показать ее только во время сбора данных. Пожалуйста, посмотрите фрагмент моего кода ниже. Вместо того, чтобы вручную вызывать анимацию загрузки, я бы хотел, чтобы она запускалась только во время работы функции «getAllDocuments». Иногда мое жестко запрограммированное значение времени слишком короткое, а другие слишком длинные. Я хотел бы, чтобы это было правильно каждый раз.


ngOnInit() {
    this.getAllDocuments();
    this.triggerLoadingAnimation(12);
  }

  ngAfterViewInit(): void {
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
  }

  public triggerLoadingAnimation(num){
    this.spinner.show();

    setTimeout(() => {
      this.spinner.hide();
    }, num*1500);
  }

  async getAllDocuments() {
    this.repoService.getData('/api/Prometheus/Documents')
    .subscribe(res => {
      this.dataSource.data = res as Document[];
    })
  }


person jak dev    schedule 04.09.2020    source источник
comment
Ознакомьтесь с этим https://www.npmjs.com/package/ng-http-loader. Это будет работать глобально http-вызовом, сделанным на бэкэнде. Не нужно скрывать и показывать загрузчик вручную.   -  person Santosh Shinde    schedule 04.09.2020
comment
запустите счетчик перед отправкой запроса и завершите его методом finalize() запроса   -  person pc_coder    schedule 04.09.2020


Ответы (5)


Вы были рядом.
Я также добавил обработку ошибок, удалил ненужную асинхронность и запустил вызов ajax в конструкторе вместо ngOnInit, чтобы избежать ненужного времени ожидания.

constructor(private repoService: RepoService) {
    this.getAllDocuments();
}

ngOnInit() {
  // stuff that really need @Input data to be filled
}

ngAfterViewInit(): void {
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
}

getAllDocuments() {
    this.spinner.show();
    this.repoService.getData('/api/Prometheus/Documents')
    .subscribe((res: Document[]) => {
      this.dataSource.data = res;
      this.spinner.hide();
    },
    error => {
      this.spinner.hide();
      console.error('error while retrieving documents', error);
      // handle error
    })
}
person Random    schedule 04.09.2020
comment
метода ошибки недостаточно для любой ошибки, вам нужно использовать метод финализации, чтобы скрыть счетчик - person pc_coder; 04.09.2020
comment
это сработало с небольшой доработкой большое спасибо! - person jak dev; 04.09.2020
comment
@pc_coder Я так не думаю. finalize срабатывает при наблюдаемом завершении. Для вызовов HTTP это всегда будет вызывать ошибку или успех. Можете ли вы указать случай, когда наблюдаемое будет завершено без запуска обработчиков успеха или ошибок? - person Random; 04.09.2020
comment
@Random, вы правы, но в этом случае вы делаете код дважды, как в случае успеха, так и в случае ошибки, финализация предназначена для этих целей. - person Mandeep Singh; 04.09.2020
comment
@MandeepSingh Я думаю, что ошибка не вызывает обратный вызов финализации. Невозможно сделать то же самое, что и try/catch/finally с Observables. - person Random; 05.09.2020

Вы делаете это неправильно, вы должны вызвать счетчик, чтобы показать, когда выполняется вызов API, и скрыть его, когда данные извлекаются.

Лучший способ - вызвать его в конструкторе, поскольку ngOnInit вызывается после завершения создания DOM компонента, внедрения всех необходимых зависимостей через конструктор и обработки входных привязок.

constructor() {
    this.getAllDocuments();
}


ngOnInit() {
    //this.getAllDocuments();
  }

  ngAfterViewInit(): void {
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
  }

  async getAllDocuments() {
    this.spinner.show();
    this.repoService.getData('/api/Prometheus/Documents')
    .subscribe((res: Document[]) => {
      this.dataSource.data = res;
    }, (err) => {
        //handle the errors
         console.log(err);
    }, () => {
        this.spinner.hide();
    });
  }
person Mandeep Singh    schedule 04.09.2020
comment
метода error недостаточно, чтобы скрыть любую ошибку, используйте один раз в методе finalize() - person pc_coder; 04.09.2020
comment
отредактировал его, обработав скрытие анимации спиннера в финализации вместо успеха и ошибки как - person Mandeep Singh; 04.09.2020

Загрузка счетчика — это хороший метод взаимодействия с пользователем, но сколько счетчиков вам нужно загрузить, чтобы удовлетворить пользователя? Вероятно, в зависимости от размера приложения. Поскольку вам нужно показывать счетчик, когда данные извлекаются, использование глобального счетчика было бы гораздо лучшим способом. С глобальным счетчиком всякий раз, когда данные извлекаются, счетчик будет отображаться. Ниже приведена хорошая реализация перехватчика, показывающая счетчик с использованием перехватчика. показать счетчик

person Owen Kelvin    schedule 04.09.2020

Вы можете использовать приведенный ниже код:

getAllDocuments() {
 this.spinner.show(); // SHOW WHEN DATA IS LOADING
    this.repoService.getData('/api/Prometheus/Documents')
    .subscribe(res => {
      this.dataSource.data = res as Document[];
     this.spinner.hide();  //  HIDE WHEN DATA IS LOADED
    })
  }
person abhay tripathi    schedule 04.09.2020
comment
эта логика неверна, вы не прячете здесь счетчик в случае ошибки! Вам нужно спрятаться в finalize - person pc_coder; 04.09.2020
comment
@pc_coder Вопрос в том, чтобы показать счетчик при загрузке данных. И я дал на него ответ. - person abhay tripathi; 04.09.2020
comment
@pc_coder Что касается другого данного решения, то даже другие не обрабатывают другие возможные случаи, например, пустой ответ, коды ошибок на стороне сервера, сбои сервера. - person abhay tripathi; 04.09.2020

Вы можете показывать и скрывать счетчик в одной и той же функции, а не создавать для этого новую функцию.

async getAllDocuments() {
    this.spinner.show();
    this.repoService.getData('/api/Prometheus/Documents')
    .subscribe(res => {
          this.dataSource.data = res as Document[];
          this.spinner.hide();
    });
    
}
person Suroor Ahmmad    schedule 04.09.2020
comment
Да, его нужно поместить внутрь. обновил ответ. - person Suroor Ahmmad; 04.09.2020
comment
эта логика неверна, вы не прячете здесь счетчик в случае ошибки! Вам нужно спрятаться в finalize - person pc_coder; 04.09.2020
comment
@pc_coder, не могли бы вы показать пример того, как ВЫ могли бы это сделать? - person jak dev; 04.09.2020