J'essaye d'écrire un code qui exécute une fonction asynchrone et quand c'est fait, il exécute un autre morceau de code.
J'ai essayé de mettre la fonction async dans une promesse (comme on le voit dans le code ci-dessous) et d'utiliser le puis
méthode sans succès.
ce qui se passe à l'intérieur de la fonction n'a pas vraiment d'importance mais je l'ai quand même inclus au cas où je me trompe et c'est le cas. .
new Promise((res) => { this.getDataAndUsername(); res(); }).then( this.CheckInDataBase(this.state.username) )
getDataAndUsername est la fonction asynchrone que j'essaie d'exécuter avant les autres fonctions.
CheckInDataBase = (username) => { console.log('checking In DataBase'); this.state.data.forEach((element)=>{ if(element.username === username){ this.setState({exist: true}); } }); if (!(this.state.exist)){ axios.post('/createUser', {"username": username, "status": "Working"}); this.setState({exist: true}); } }
c'est la fonction habituelle que j'essaie d'exécuter après l'asynchrone
et voici le code:
getData = async(file) =>{ let data = await fetch(file); data = await data.text(); return(data); } getDataAndUsername = async() => { this.setState({data: JSON.parse(await this.getData("/getData"))}); this.setState({username: await this.getData("/user")}); console.log('done'); }
ce qui se passe en ce moment c'est que , le this.CheckInDatabase s'exécute avant la fin de getDataAndUsername.
3 Réponses :
Essayez :
(async function() { try { const dataAndUsername = await this.getDataAndUsername(); /** * Your code that you want to run after getDataAndUsername */ } catch(e) { /** * Handle error here */ } })();
Ou avec async/await
:
this.getDataAndUsername().then((response) => { /** * Your code that you want to run after getDataAndUsername */ }, (error) => { /** * Handle error here */ });
C'est bizarre ... Je me souviens avoir essayé ça et ça n'a pas marché, mais de toute façon ça marche maintenant, merci beaucoup!
Étant défini comme async
, votre getDataAndUsername
est déjà une promesse, il n'est pas nécessaire de l'envelopper dans une nouvelle promesse ()
. Vous pouvez simplement faire:
new Promise((res) => { return this.getDataAndUsername().then(_ => {res()}) }) ...
Et cela devrait fonctionner.
Vous étiez en train de créer un nouvelle promesse avec ceci:
new Promise((res) => { this.getDataAndUsername(); res(); }) ...
Là, vous appelez this.getDataAndUsername ()
, mais ignorez si cela résout ou non. Ce code appellera res
instantanément, donc checkInDatabase
a été appelé avant que getDataAndUsername
ne soit résolu.
Vous avez froid, à la place, attendez pour getDataAndUsername
à résoudre:
this.getDataAndUsername().then( _ => { this.CheckInDataBase(this.state.username); })
Le but serait d'attendre la résolution de la promesse en utilisant puis
, et aussi ajouter un return
.
Cependant, comme indiqué ci-dessus, il n'est pas nécessaire de le faire car getDataAndUsername
est déjà une promesse.
Merci beaucoup pour la réponse détaillée! vous avez été vraiment utile!
Il y a toujours un problème: this.getDataAndUsername ()
met à jour l'état de manière asynchrone et il y a un risque que this.CheckInDataBase (this.state.username)
. this.state.username
et this.state.data
peuvent être anciens au moment de la boucle sur les données
et la fonctionnalité plantera dans ce Cas
Comme je l'ai écrit dans les commentaires, vous mettez à jour l'état trop souvent. C'est un processus asynchrone, donc vous pourriez finir par vérifier ou boucler un ancien état.
Je vous suggère d'utiliser this.setState
le moins possible et de renvoyer les valeurs à la place dans autant de fonctions que possible. De cette façon, vous diviserez la fonctionnalité et ne vous reposerez pas sur l'état de react.
Voici ma proposition pour votre problème:
class App extends React.PureComponent { getData = async (file) =>{ let data = await fetch(file); return await data.text(); }; getDataAndUsername = async () => ({ data: JSON.parse(await this.getData("/getData")), username: JSON.parse(await this.getData("/user")) }); checkInDataBase = ({ username, data }) => { console.log('checking In DataBase'); return !!data.find(element => element.username === username); }; addUser = async username => await axios.post('/createUser', {"username": username, "status": "Working"}); myCheckFunction = async () => { const dataAndUsername = await this.getDataAndUsername(); if (dataAndUsername) { if (!this.checkInDataBase(dataAndUsername)) { const newUser = await this.addUser(dataAndUsername.username); dataAndUsername.data.push(newUser); } // A single place where you update the state this.setState({ ...dataAndUsername, exists: true }) } } }
Merci beaucoup d'avoir pris votre temps pour m'aider à réaliser et à résoudre mes erreurs! vous avez été vraiment utile!
Pourquoi n'attendez-vous pas
this.getDataAndUsername ();
?@sjahan parce qu'ils ne sont pas dans une fonction asynchrone, je ne peux pas
Vous utilisez trop souvent this.setState dans vos fonctions. Cela fonctionne de manière asynchrone. Essayez de renvoyer les valeurs au lieu de mettre à jour l'état.
CheckInDataBase
peut avoir un problème: lethis.setState ({exist: true});
à l'intérieur de la boucle peut ne pas être propagé avant leif (! (this. state.exist))
s'exécute@eitanr si votre fonction attend quelque chose, alors c'est
async
, alors pourquoi ne pas lui donner le mot-cléasync
?