2017-10-02 2 views
-3

Je cherchais un moyen de comprendre ce problème et m'excuser si mes compétences de recherche ne sont pas à la hauteur.Chaîne .then fonctions dans ES6 chercher appel

Mon numéro: Je récupère une API et je veux savoir quand toutes les données ont été entièrement chargées. En lisant les documents, il semble que je puisse enchaîner les déclarations .then avec fetch et je pensais que cela fonctionnerait. Mais, il semble qu'ils semblent tous tirer en même temps sans attendre le précédent.

Voici mon code:

fetch(myUrl, { 
    method: 'post', 
    headers: { 
     'Content-Type': 'application/json; charset=utf-8',    
    }, 
    credentials: 'include',   
    body: data 
    })         
     .then(fetchStatus) 
     .then(json) 
     .then(function(msg){          
      showSearchResults(); 
      setTimeout(function(){ console.log("Next then should fire after this"); }, 4000);         
     }) 
     .then(function(){ 
      return console.log("The 2nd is firing!");         
     }); 

function fetchStatus(response) { 
    if (response.status >= 200 && response.status < 300) { 
     return Promise.resolve(response) 
    } else { 
     return Promise.reject(new Error(response.statusText)) 
    } 
} 

function json(response) { 
    return response.json() 
} 

C'est grand si elle est asynchrone, mais ces événements doivent être synchrones en raison du fait que je suis en train de travailler avec le contenu créé par le précédent appel, showSearchResults();

Toute aide est très appréciée.

+0

Si vous utilisez ES6 ne pas oublier le 'msg => {... } 'notation de fonction. Il peut économiser beaucoup de verbosité et évite la danse 'var self = this'. – tadman

+0

essayez d'emballer 'showSearchResults' dans Promise.all et attendez que cela se résolve – maioman

+0

On ne sait pas quel est le problème ici. Vous avez un seul appel 'fetch', et chaque gestionnaire de cette chaîne ne s'exécute que lorsque le précédent s'exécute. Quel est le problème, exactement? (De plus: ne devriez-vous pas fournir une sorte d'argument à 'showSearchResults'?) –

Répondre

0

chaînant .then ne garantit pas que le code exécute de façon séquentielle, sauf si vous avez retourné une promesse de l'appel .then précédent. Dans votre exemple, si vous voulez que le second console.log s'exécute après showSearchResults, vous devriez return showSearchResults() et enchaînez votre .then sur cela (ceci ne fonctionne que si showSearchResults renvoie une promesse, si ce n'est pas le cas, vous voudrez l'envelopper dans une similaire à comment vous avez pour fetchStatus).

De même, si vous voulez une chaîne .then hors d'un setTimeout, vous pourriez écrire quelque chose comme:

fetch(url, { method: 'post', etc... }) 
    .then(fetchStatus) 
    .then(json) 
    .then(function(msg){ 
     return new Promise(function(resolve, reject){ 
     setTimeout(function() { 
      console.log("Next then fires after promise resolves"); 
      resolve(); 
     }, 4000) 
     }) 
    }) 
    .then(function(){ 
     console.log("Second is firing") 
    }) 
    .catch(err => console.log(error)) // always remember to catch errors! 
+0

Cela fonctionne exactement comme j'espérais que cela fonctionne. J'ai essayé cette méthode avant de poster, mais je n'ai pas eu le "nouveau" mot-clé dans ma promesse et lutté avec cela pendant un moment. Merci de votre aide! – zadees

-1

Vos appels successifs à la fonction then représentent une chaîne de rappels à la même promesse, qui est la première. Ils ne représentent pas toutes les autres promesses et c'est pourquoi ils s'exécutent si vite. Ce que vous devez faire est de les chaînes à la place dans les fonctions de rappel comme indiqué ci-dessous:

fetch(myUrl, { 
    method: 'post', 
    headers: { 
    'Content-Type': 'application/json; charset=utf-8', 
    }, 
    credentials: 'include', 
    body: data 
    } 
).then((response) => { 
    // fetch promise is resolved 
    fetchStatus(response).then((response) => { 
     // fetchStatus promise is resolved 
     json(response).then((msg) => { 
      // json promise is resolved 
      showSearchResults(); 
      setTimeout(function(){ 
       console.log("Next then should fire after this"); 
      }, 4000); 
      // note that this log will execute before the previous one because 
      // `setTimeout` does not return a promise 
      console.log("The 2nd is firing!"); 
     }); 
    }); 
}); 

function fetchStatus(response) { 
    if (response.status >= 200 && response.status < 300) { 
     return Promise.resolve(response) 
    } else { 
     return Promise.reject(new Error(response.statusText)) 
    } 
} 

function json(response) { 
    return response.json() 
}