2017-08-15 1 views
1

Je suis aux prises avec fetch(), que j'utilise pour récupérer JSON. I pense le problème est que le code se termine et essaie d '«agir» sur le tableau avant que fetch() l'ait effectivement téléchargé et traité. J'ai d'abord écrit une version plus simple, ce qui a entraîné le même problème; la plupart du code ici is from Google Developers.Javascript: comment s'assurer que fetch() est fini avant d'utiliser les données?

Comme indiqué ci-dessous (setTimeout uniquement inclus pour démontrer le problème) je reçois des résultats différents pour accéder au même tableau deux fois, une seconde d'intervalle:

dataResultArray = requestJSONResult(searchString); 

console.log(dataResultArray);   // logs '[]' 
console.log(dataResultArray.length); // logs '0' 

setTimeout(function(){ 
    console.log(dataResultArray);   // logs the actual JSON array contents 
    console.log(dataResultArray.length); // logs the real array length 
}, 1000); 


function requestJSONResult(searchString) { 
    var tempArray = [] 

    fetch(`/search/?term=${searchString}`) 
    .then(status) 
    .then(json) 
    .then(function(data) { 
     tempArray.push(...data) 
    }).catch(function(error) { 
    console.log('Request failed', error); 
    }); 

    return tempArray; 
} 

function status(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() 
} 
+0

google javascript promesses et/ou rappels – yBrodsky

+0

Vous devez utiliser correctement les promesses. Renvoyez la promesse de votre fonction et attachez-y un gestionnaire 'then', au lieu d'essayer de pousser le résultat dans un tableau. Il n'y a aucun moyen qui fonctionnera de manière fiable. – Amy

+0

Une fois que vous utilisez des promesses, respectez les rappels 'then', même dans votre script principal qui appelle ces fonctions. Vous pouvez uniquement accéder aux données récupérées de manière asynchrone à cet endroit. – trincot

Répondre

2

Il semble que vous essayez de faire votre synchrone de code asynchrone ce n'est pas une bonne idée.

juste retour la promesse de chercher à récupérer les données comme ceci:

function requestJSONResult(searchString) { 
    return fetch(`/search/?term=${searchString}`) 
    .then(status) 
    .then(json); 
} 

function status(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() 
} 


requestJSONResult(searchString) 
    .then(function(data) { 
    console.log(data); 
    console.log(data.length); 
    }) 
    .catch(function(error) { 
    console.log('Request failed', error); 
    }); 

Maintenant, votre requestJSONResult retourne une promesse qui pourrait soit résoudre ou de rejeter de sorte que tout appelant peut attendre ces événements.

1

Gardez à l'esprit que je n'ai pas testé cela. Vous devez utiliser des promesses tout au long. Essayer de forcer le code synchrone asynchrone n'est pas fiable, comme vous l'avez découvert.

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

ligne 2 Avis de requestJSONResult: return fetch(....). Nous retournons la promesse de la fonction.

function requestJSONResult(searchString) { 
    return fetch(`/search/?term=${searchString}`) 
     .then(status) 
     .then(function(response) { 
      return response.json(); 
     }) 
     .catch(function(error) { 
      console.log('Request failed', error); 
     }); 
} 

requestJSONResult(searchString) 
    .then(function(result) { 
     console.log(result); 
    });