RxJs Угловая многократная синхронизация http webcalls - PullRequest
1 голос
/ 14 октября 2019

Я должен сделать несколько синхронизированных веб-звонков, один за другим, если статус нормальный.

Ужасный, но рабочий код:

        this.api.post1().subscribe((data: any) => {
          if (data.status== 'OK') {

            this.api.post2().subscribe((data: any) => {
              if (data.status== 'OK') {

                this.api.post3().subscribe((data: any) => {
                  if (data.status== 'OK') {

                    this.api.post4().subscribe((data: any) => {
                      if (data.status == 'OK') {
                        // Do something
                      }else{
                        console.log('error: ' + data.status);
                      }
                    });

                  }else{
                    console.log('error: ' + data.status);
                  }
                });

              }else{
                console.log('error: ' + data.status);
              }
            });

          }else{
            console.log('error: ' + data.status);
          }
        });

Я пытаюсь использовать concatMap

const post1$ = this.api.post1();
const post2$ = this.api.post2();
const post3$ = this.api.post3();
const post4$ = this.api.post4();

from([post1$, post2$, post3$, post4$]).pipe(
      concatMap(a => a)
    ).subscribe(res => console.log(res));

Но мне нужно проверить, каждый ли ответ здесь хорошо. Есть ли в этом прекрасное решение?

Ответы [ 3 ]

2 голосов
/ 14 октября 2019

Я бы порекомендовал вам использовать конвейерные операторы RxJS и обрабатывать ошибки в цепочке конвейеров. Вы можете использовать switchMap для формирования цепочки запросов, а также throwError для завершения цепочки и выдачи наблюдаемых ошибок.

this.api.post1()
  .pipe(
    switchMap(res => {
      if (data.status === 'OK') {
        return of(this.api.post2());
      } else {
        console.log('error: ' + data.status);
        return throwError('Twos are bad');
      }
    }),
    switchMap(res => {
      if (data.status === 'OK') {
        return of(this.api.post3());
      } else {
        console.log('error: ' + data.status);
        return throwError('Twos are bad');
      }
    }),
    switchMap(res => {
      if (data.status === 'OK') {
        return of(this.api.post4());
      } else {
        console.log('error: ' + data.status);
        return throwError('Twos are bad');
      }
    }),
).subscribe(res => {
  console.log(res);
  // do the rest here
}, error => {
  // handle error
})
0 голосов
/ 14 октября 2019

Вот еще один подход:

import { concat, of } from 'rxjs';
import { delay } from 'rxjs/operators';

var post1$ = of({status: "OK", data: 1});
var post2$ = of({status: "OK", data: 2});
var post3$ = of({status: "!OK", data: 3});
var post4$ = of({status: "OK", data: 4});

var runSubscribe = (
  data: {status: string, data: any}, 
  chainStatus: {index: number, hasError: boolean}) => {
  if( chainStatus.hasError){
    return;
  }
  chainStatus.index++;
  if (data.status !== 'OK') {
    console.log('error: ', data.status, data.data);
    chainStatus.hasError = true;
    return;
  }
  processData(chainStatus.index, data.data);
}

var processData = (index, data) => {
  // you should put your "Success" processing function based on index
  // I just randomly delay to up to 1000 msec
  const random = Math.random()*1000;
  delay(random);
  console.log(`${index} success:`, data, random);
}


const status = {
  index: -1,
  hasError: false
}
console.clear();
concat(post1$, post2$, post3$, post4$).subscribe(
  data => runSubscribe(data, status)
);

Он остановится на 3-й наблюдаемой, так как его статус не "Хорошо".

смотрите здесь: https://stackblitz.com/edit/typescript-35hdyb

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

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

const post1$ = this.api.post1();
const post2$ = this.api.post2();
const post3$ = this.api.post3();
const post4$ = this.api.post4();

concat([post1$, post2$, post3$, post4$]).pipe(
  switchMap(data => {
    if (data.status !== "OK") {
      return throwError("Some error");
    }

    return of(data);
  })
).subscribe(res => console.log(res));

ИЛИ: Если вам нужно узнать что-то конкретное о каждой из наблюдаемыхВы можете использовать concat, но перед тем, как попасть в concat, передайте значение через каждую из конечных точек.

const handleResponse = (type: string) => 
    (responseObs) => responseObs.pipe(
      switchMap(data => {
        if (data.status !== "OK") {
          return throwError("Some error about " + type);
        }

        return of(data);
      })
    );

const post1$ = this.api.post1().pipe(handleResponse("Post 1"));
const post2$ = this.api.post2().pipe(handleResponse("Post 2"));
const post3$ = this.api.post3().pipe(handleResponse("Post 3"));
const post4$ = this.api.post4().pipe(handleResponse("Post 4"));

concat([post1$, post2$, post3$, post4$]).subscribe(res => console.log(res));
...