2017-10-04 5 views
0

J'ai un service dans une application angulaire 4 qui récupère un nombre variable de pages à partir d'une API back-end.Comment récupérer des requêtes HTTP paginées à partir d'une API backend à l'aide d'Observables dans Angular4

J'ai regardé la réponse ici Angular 2 - Chaining http requests, ce qui suggère d'utiliser un flatMap, mais cette approche ne fonctionne pas car elle nécessite que toutes les demandes soient connues au préalable. Cela ne fonctionnera pas dans mon cas puisque le nombre de requêtes et l'URL de chaque requête est dynamique et inconnu.

Le nombre de pages/demandes est déduit du résultat de la demande précédente. Donc, si la requête précédente renvoie quelque chose, la page suivante est demandée pour voir s'il y a plus d'éléments.

J'ai essayé le suivant

this.items = []; 
_fetch(url, page) { 
    this.http.get(`${url}&pageSize=2&page=${page}`).subscribe(response => { 
    this.items.concat(response.json().items) 
    // if the list of items is not empty fetch another page 
    if (response.json().items.length > 0) { 
     this._fetch(url, ++page); 
    } 
    }); 
    return Observable.of(this.items); 
} 

Cependant this.items est retourné avant que les demandes ont une chance de remplir il est toujours retourné comme une liste vide.

des idées?

+0

Regardez ceci: https://stackoverflow.com/questions/40529232/angular-2-http-observables-and-recursive-requests –

+0

la réponse liée en double ne résout pas ce problème. la question n'est pas un doublon –

Répondre

0

Depuis .subscribe renvoie un observable, vous pouvez simplement les enchaîner. Tant qu'il n'y a pas d'erreur, il va exécuter le second:

this.http.get('some url').subscribe(result => { 
    if (result) { 
     // good to go execute second call. 
     this.http.get('other url').subscribe(result2 => { 
      // do something with result 1 and result 2 
     }) 
    } else { 
     // handle error. don't execute second call 
    } 
}, error => { 
    // error occured. don't execute second call 
}) 

Vous pouvez aussi quelques promesses de configuration dans votre application comme ceci:

firstHttpCall() { 
    return new Promise((resolve, reject) => { 
     this.http.get('someurl').subscribe(result => { 
      result(result); 
     }, error => { 
      reject(error); 
     }); 
    }); 
} 
secondHttpCall() { 
    return new Promise((resolve, reject) => { 
     this.firstHttpCall().then(result => { 
      resolve(result); 
     }, error => { 
      reject(error); 
     }); 
    }); 
} 
someOtherCall() { 
    // some stuff... 
    this.secondHttpCall().then(result => { 
     // everything went well. 
    }, error => { 
     // something went wrong 
    }) 
} 

Si vous pouviez arriver au point où vous n'étiez pas dépendant de la valeur des premiers appels utilisés dans le deuxième appel, je dirais que Promise.all est également une option viable.

+0

comment puis-je les enchaîner quand je ne sais pas si je devrai faire une autre demande jusqu'à ce que le premier se termine? –

+0

Je ne peux jamais arriver à ce point parce que je n'ai aucun moyen de savoir ce que l'arrière retournera à l'avance. –

+2

Évitez d'enchaîner utiliser flatmap: https://stackoverflow.com/a/34107312/2015408 –

2

Vous pouvez utiliser flatMap pour enchaîner les ensemble observables

fetch(url){ 
    return this.http.get(`${url}/initial-api/`) 
     .flatMap(res => { 
      let page = res.page 

      return this.get(`${url}&pageSize=2&page=${page}`); 
     }); 
} 

Maintenant, lorsque vous vous abonnez à la séquence observable, il va enchaîner les apis ensemble

Voici une bonne lecture sur flatMap/mergeMap: Ce qui est bien avec flatMap, c'est de garder les choses dans un seul flux, contrairement aux abonnements imbriqués qui peuvent être assez compliqués en fonction de votre code.