Wczytywanie asynchronicznie danych z wielu wywołań do jednej zmiennej

0

Hej
Jak zarobić, aby wyniki wywołań każdego GET'a były zapisywane do wspólnej zmiennej?

this.friends = [];

this.users.forEach(user => {
  this.usersService.searchUserFriends(user.login).subscribe(data => {
      this.friends = this.friends.concat(data);
  });
});

Na razie friends ma tylko wynik z jednego wywołania.

1

Spróbuj tak

this.friends = [];

this.users.forEach(user => {
  this.usersService.searchUserFriends(user.login).subscribe(data => {
      this.friends.push(data);
  });
});
1

Normalnie jak byś to miał na promisach masz wtedy Promise.all() i wynik wszystkich wrzucasz do jednej zmiennej

const result = Promise.all(this.users.map(user => Promise.resolve(user.login))); // przykład poglądowy

Dawno z RxJS nic nie pisałem, ale podejrzewam ze ZIP tutaj pomoże i potem subscribe na tego zipa.
https://www.learnrxjs.io/learn-rxjs/operators/combination/zip
albo forkJoin
https://www.learnrxjs.io/learn-rxjs/operators/combination/forkjoin

1

Tylko że rozwiązanie @szok z Promise.all(), musisz wiedzieć że jeśli pojedynczy login sfailuje, to cały Twój promise sfailuje.

Z pętlą wczytasz wszystkie które się udały.

wiec wybierz które Ci bardziej pasuje.

1

To wtedy Promise.allsettled i mamy lepsza kontrole. Ale tutaj jest RxJS, z jego bajerami, wiec promisy odpadaja.

1

Co ma robić kod riddla to nie wiem, typ zamienił concat, które pozwala dodać tablicę do tablicy, na push, co działa dla jednego obiektu i mówi że jego rozwiązanie jest zajebiste xD
Dodatkowo żądania GET są asynchroniczne, samo dodawanie do tablicy bez async await albo bez zamiany na Promise nic nie da

Dzieki @szok

Zrobiłem async await i użyłem observable.toPromise()

0
Mariuszek39 napisał(a):

Co ma robić kod riddla to nie wiem, typ zamienił concat, które pozwala dodać tablicę do tablicy, na push, co działa dla jednego obiektu i mówi że jego rozwiązanie jest zajebiste xD

Jak chcesz dodać wszystkie to możesz zrobić this.friends.push(...data); i dodać wszystkie na raz?

Mariuszek39 napisał(a):

Dodatkowo żądania GET są asynchroniczne, samo dodawanie do tablicy bez async await albo bez zamiany na Promise nic nie da

No da, w momencie w którym wszystkie calle się skończą, to w this.friends będziesz miał wszystkie elementy.

Oczywiście jak zrobisz taką głupotę jak to:

this.friends = [];

this.users.forEach(user => {
  this.usersService.searchUserFriends(user.login).subscribe(data => {
      this.friends.push(...data);
  });
});

console.log(this.friends); // tutaj

Czyli po tej pętli spróbujesz je odczytać, to oczywiście że ich tam nie będzie jeszcze, bo ten console.log() (czy czymkolwiek odczytasz te wartości) wywoła się zanim calle się skończą.

Bo Tobie nie chodzi o to, że wczytać wszystkie dane z callabli, tylko o to jak poczekać aż wszystkie się załadują - więc tak powinieneś zadać pytanie.

2

Nie wiem co wy macie z tymi Promisami, po to są w Angularze Observable i biblioteka RxJs żeby na nich operować.

// utworz tablice requestow
const requests: Observable<User[]>[] = [];
for (let i = 0; i < 3; i++) {
  requests.push(this.userService.getUsers());
}

// pusc je rownolegle
const usersFromRequests$ = forkJoin(requests).pipe(
  map(usersArrays => ([] as User[]).concat(...usersArrays))
);

usersFromRequests$.pipe(
  tap(usersArrays => console.log(usersArrays))
).subscribe();

forkJoin - puszcza równolegle requesty
([] as User[]).concat(...usersArrays) - spłaszcza wielowymiarową tablicę userów do jednowymiarowej

Ja bym trzymał strumień usersFromRequests$ i przekazał je potem za pomocą async pipe zamiast zapisywać je do zmiennej w komponencie

1 użytkowników online, w tym zalogowanych: 0, gości: 1