Angular делает несколько HTTP-запросов, но ждет завершения каждого из них, прежде чем делать новый - PullRequest
0 голосов
/ 12 декабря 2018

В угловом приложении у меня есть массив литеральных объектов, содержащих свойство url.Мне нужно сделать запрос http для каждого из этих объектов, но один за другим.

пример:

let arr = [{url: 'http://example.com/url1'},{url: 'http://example.com/url2'},{url: 'http://example.com/url3'}]

(например, они могут быть больше объектов, и яне знаю сколько)

Теперь я хочу сделать запрос на первый URL-адрес, и когда у нас будет ответ (или ошибка, не имеет значения), ТО я хочу сделать запрос на второйи т.д. Любая идея, как эффективно реализовать это?

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

Ответы [ 5 ]

0 голосов
/ 07 февраля 2019

Возможным решением будет использование concatMap , toArray и switchMapTo .

Итак, сначала у вас есть список URL:

let arr = [{url: 'http://example.com/url1'},{url: 'http://example.com/url2'}]

Затем вы преобразуете их в наблюдаемую:

of(arr)
.pipe(
   concatMap(r=> http.get(r.url)), //MAKE EACH REQUEST AND WAIT FOR COMPLETION
   toArray(), // COMBINE THEM TO ONE ARRAY
   switchMapTo(http.get("FINALURL") // MAKE REQUEST AFTER EVERY THING IS FINISHED
)).subscribe()
0 голосов
/ 12 декабря 2018

Вы можете комбинировать свои наблюдаемые с flatMap.Поскольку у вас есть список наблюдаемых (или список URL, которые вы хотите преобразовать в наблюдаемые), вы можете сделать это с помощью reduce.

Пример:

// just some options to make a simple GET without parsing JSON
// and reading the response status
const httpOptions = {
  headers: new HttpHeaders({
    'Accept': 'text/html, application/xhtml+xml, */*',
    'Content-Type': 'application/x-www-form-urlencoded'
  }),
  responseType: 'text',
  observe: 'response'
}; 

const urls = [
  { url: 'www.google.com' },
  { url: 'www.stackoverflow.com' },
  { url: 'www.imgur.com' },
  { url: 'www.reddit.com' },
];

const reducer = (cur, acc) => acc.pipe(
  flatMap(r => cur)
);

const all$ = urls.map(({url}) => 
                    // create the get requests
                    http.get(url, httpOptions).pipe(
                      // do something with the result
                      tap(r => console.log(r.url + ': ' + r.status))
                 ))
                 .reverse()
                 .reduce(reducer);

all$.subscribe(x => {});
0 голосов
/ 12 декабря 2018

Используйте concatAll () метод из rxJs, который собирает наблюдаемые и подписывается на следующий, когда завершается предыдущий.(Или вы можете использовать forkJoin для нескольких запросов одновременно.)

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

Он принимаетмассив в качестве параметра.например -

    let response1 = this.http.get(requestUrl1);
    let response2 = this.http.get(requestUrl2);
    let response3 = this.http.get(requestUrl3);
    return Observable.forkJoin([response1, response2, response3]);

Для исх.- https://medium.com/@swarnakishore/performing-multiple-http-requests-in-angular-4-5-with-forkjoin-74f3ac166d61

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

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

0 голосов
/ 12 декабря 2018

Мы можем использовать хитрый метод для этого.Вы должны создать метод в сервисе, как показано ниже.

// TestService.ts
callUrlAsync(url): any[] {
    return this._http.get<any>(url);
  }

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

//component.ts

let arr = [{url: 'http://example.com/url1'},{url: 'http://example.com/url2'}, 
{url:'http://example.com/url3'}]

public i = 0;

//trigger method
testMethod(){
this.callUrl(this.arr[0]);
}

callUrl(url){
this.testService.callUrlAsync(url)
  .subscribe(data => {
    console.log(data);
      if(this.arr.length > this.i){
      this.i++;
      this.callUrl(this.arr[this.i]);
}
  }
  }, error => {
    this.Error(error);
    if(this.arr.length > this.i){
    this.i++;
    this.callUrl(this.arr[this.i]);
}
  }
  );
}
0 голосов
/ 12 декабря 2018

Пользователь forkJoin Fork Join

let arr = [{url: 'http://example.com/url1'},{url: 'http://example.com/url2'},{url: 

'http://example.com/url3'}]

forkJoin(arr);
...