1
votes

Fonction d'exécution après la fonction asynchrone en javascript

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.


4 commentaires

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: le this.setState ({exist: true}); à l'intérieur de la boucle peut ne pas être propagé avant le if (! (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 ?


3 Réponses :


-1
votes

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
   */
});


1 commentaires

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!



3
votes

É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.

Pourquoi votre code n'a pas fonctionné au départ

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.


2 commentaires

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



0
votes

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
      })
    }
  }
}


1 commentaires

Merci beaucoup d'avoir pris votre temps pour m'aider à réaliser et à résoudre mes erreurs! vous avez été vraiment utile!