Вызов метода с подпиской, как ждать возврата типа подписки? - PullRequest
0 голосов
/ 29 октября 2019

Так что моя проблема, надеюсь, относительно проста для решения. Итак (Angular 8 между прочим) я вызываю метод, и внутри этого метода я подписываюсь на вызов API. Все работает, за исключением того, что return всегда вызывается через секунду или две после метода, а возвращаемый тип никогда не возвращается должным образом. Я пробовал MAP, но это не работает должным образом. Позвольте мне привести небольшой пример:

return this.callApi( apiObject ); // I want to wait for subscribe and return data here

callApi( apiObject ) {
  this.myApiService.someRandomPostApiCall( apiObject ).subscribe(res => {
            console.log(res);
            res.valid ? { return true } : { return false };
    });
}

Ответы [ 3 ]

1 голос
/ 29 октября 2019

Если вы хотите реагировать на испускание элемента (в основном в ожидании получения данных), лучше всего подписаться на компонент, где он вам нужен, а не на саму функцию.

return this.callApi( apiObject ).subscribe(//do stuff here);

callApi( apiObject ) {
  return this.myApiService.someRandomPostApiCall( apiObject )
}

Вот пример из одного из моих приложений:

В сервисе

  getProducts(): Observable<IProduct[]> {
    return this.http.get<IProduct[]>(this.productUrl)
      .pipe(
        tap(data => console.log('All: ' + JSON.stringify(data))),
        catchError(this.handleError)
      );
  }

В компоненте

  ngOnInit(): void {
    this.productService.getProducts().subscribe({
      next: products => this.products = products,
      error: err => this.errorMessage = err
    });
  }

Вы можете увидеть весь источник здесь:

https://stackblitz.com/edit/github-angular-getting-started-final

0 голосов
/ 30 октября 2019

Реальный ответ заключается в том, что вы не можете.

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

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

Если вы можете предоставить его, мы можем найти наилучший способ выполнить эту работу.

Позвольте мне объяснить вам, что происходит в вашем коде, нумерация строк по времени _execution:

// I'm splitting the rows, just to better describe the order of execution
const somethingThatYouDonTExpect = this.callApi(apiObject);  // this runs first
return somethingThatYouDonTExpect;  // this runs third, returning a subscription object

callApi(apiObject) {
  // this runs second and returns IMMEDIATELY a subscription object, NOT a result
  return this.myApiService.someRandomPostApiCall( apiObject ).subscribe(res => {
            console.log(res); // this runs fourth, and the return is completely useless: subscribe is not expected to return anything.
            res.valid ? { return true } : { return false };
    });
}
0 голосов
/ 29 октября 2019

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

callApi(apiObject) {
  let promise = new Promise((resolve, reject) => {
    let apiURL = `media=music&limit=20`;
    this.http.get(apiURL)
      .toPromise()
      .then(
        res => { 
         // Success
         console.log(res);
         resolve();
        }, (msg) => { 
         // Error
         reject(msg);
        }
      );
  });
  return promise;
 }
}
...