Как получить данные через HTTP без использования обещаний - PullRequest
0 голосов
/ 18 марта 2020

У меня есть следующий сервисный код, который я упростил для публикации здесь

    Load(Channel: any) {
        // 
        let URL = Globals.AppSiteRoot + Channel.URL
        return this.LoadData(URL)
    }

    Load_Default() {
        let URL = Globals.AppSiteRoot + "dir1/somedata.XML"
        console.log("XYZService.Load_Default------.------>>URL", URL)
        //
        return this.LoadData(URL)
            .then(data => {
                {
                    // do some processing here
                    console.log("XYZService.Load_Default<<P------.------data", data)
                    console.log("XYZService.Load_Default<<P------.------This.Data", this.Data)
                }
            });
    }

    // https://medium.com/@balramchavan/using-async-await-feature-in-angular-587dd56fdc77
    // https://v5.angular.io/api
    // https://v5.angular.io/guide/comparing-observables
    LoadData(URL: string) {  // : Observable<any>

        return new Promise(resolve => {
            // first argument is URL, put config as second argument
            // return this.http.get(URL, {responseType: 'text'})
            this.HttpClient.get(URL)
                .map(res => res)
                .subscribe(
                    data => {
                        // 
                        console.log("XYZService.LoadData<<P------.------http.get=>data", data)
                        // Do some processing here, if needed...
                        this.Data = data
                        // return new Observable(this.Data);  
                        resolve(this.Data)
                    }
                    ,
                    err => {
                        // https://forum.ionicframework.com/t/handle-errors-with-http-services/53229
                        console.log("XYZService.LoadData<<P------.------http:ERR", err)
                    }
                );
        });
    }

В компоненте XYZ я делаю следующее:

Show(Channel: any) {
        console.log("XYZComponent.Show------.------>>Channel>>" + Channel.URL)
        //
        this.XYZService.Load(Channel)
            .then(data => {
                console.log("XYZComponent.Show------.------>>data", data)  
                this.NavController.parent.select(1);
            });            
    }

Если я переключаюсь на использование async / await мой код компонента становится таким, и я должен признать, что как только кто-то принимает await блокирует, код кажется более чистым, чем использование Promise .then ....

    async ShowV2(Channel: any) {
        console.log("XYZComponent.Show------.------>>Channel>>" + Channel.URL)
        //
        const data = await this.XYZService.Load(Channel)
        console.log("XYZComponent------.------>>data", data)
        // 
        this.NavController.parent.select(1)
    }

Я получаю смешанные сообщения из многих постов и блогов, которые я читаю.

Некоторые говорят, что не используйте HttpClient.get.subscribe, если вы ожидаете получать данные только один раз ... вместо этого используйте .toPromise (), однако они никогда не показываются как обрабатывать ошибки.

Некоторые говорят, что async / await - это всего лишь сахарный синтаксис, все еще использующий Promises.

Некоторые говорят, что Observables намного лучше, и даже Angular широко их использует.

Относительно кода в .Load () .Load_Default () и компонентах .Show () - это те места, где можно ожидать Observables и как его кодировать как таковой?

Я использовал ReplaySubject ( 1) в другом месте, чтобы брат оповещать о событиях от сервисов и косвенно общаться со страницы на страницу. Однако я не уверен, что это еще одно место для его использования.

Моя типичная проблема с источниками событий, такими как ReplaySubject (1), особенно когда я посещаю код несколько месяцев спустя,

1 ) Как я гарантировал, что подписался на событие только один раз? где?

2) Отписался ли я и где?

Кстати, хотя я использую Promises, Observables, ReplaySubject (1), это все для меня по-китайски, и это большой источник отвлечения и разочарования чтобы достичь моей простой цели - показать некоторые данные или картинки, которые я извлекаю из Интернета. Поэтому, если у вас есть подход / шаблон, чтобы четко изложить код, чтобы, когда я вернусь через четыре месяца, это все имело смысл:)

Пожалуйста, включите код шаблона с обработкой ошибок, которую вы будете использовать в производстве. Спасибо за то, что поделились своими мыслями.

npm show ionic version
5.4.16
npm show cordova version
9.0.0
npm show angular version
1.7.9
show @angular/core version
9.0.6
ng --version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 9.0.4
Node: 10.16.0
OS: win32 x64

Angular: 5.0.3
... common, compiler, compiler-cli, core, forms, http
... platform-browser, platform-browser-dynamic
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.4 (cli-only)
@angular-devkit/build-optimizer   0.0.35
@angular-devkit/core              9.0.4 (cli-only)
@angular-devkit/schematics        9.0.4 (cli-only)
@schematics/angular               9.0.4 (cli-only)
@schematics/update                0.900.4 (cli-only)
rxjs                              5.5.2
typescript                        2.8.3
webpack                           3.12.0

1 Ответ

2 голосов
/ 18 марта 2020

Я предлагаю использовать Observables вместо Promises, поскольку Angular часто используют первое и способствуют развитию реактивного стиля.

Рассмотрим следующий пример кода:

@Injectable({
  providedIn: 'root'
})
export class SomeService {
  private readonly URL: string = 'someurl';

  constructor(private http: HttpClient) {}

  public loadData(): Observable<any> {
    return this.http.get(this.URL).pipe(
      // if you want to handle errors you can use the catchError operator
      // however, a better way is to use a HTTP Interceptor instead
      // if you want to see how you can handle errors with the interceptor let me 
      // know
      catchError(error => throwError(error)),
      map(res => // do some transformation if you need),
      tap(res => // add some side effects if you need)

     // don't subscribe in the service - it is considered to be a bad practice
  }
}

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

Хотя очень важно отписаться от наблюдаемых, чтобы избежать памяти Утечки, Angular управляет для вас этим для HttpClient, поэтому вам не нужно отписываться вручную.

Для всех других наблюдаемых вы можете использовать такие операторы, как take, first, last, takeUntil или сохраните подписку в свойстве типа Subscription и отмените подписку в хуке жизненного цикла OnDestroy (то же самое необходимо сделать в случае оператора takeUntil, когда вы вызываете next и завершаете / отписываетесь для его аргумента, который является Subject).

Если вы хотите вместо этого использовать Обещания, для обработки ошибок вы можете использовать блок trycatch. * 10 21 *

Я создал стек-блиц здесь , где я включил перехватчик ошибок.

Убедитесь, что в массиве provider добавлен перехватчик из модуля приложения, например:

providers: [{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }],
...