0
votes

Javascript Async Await attend que deux fonctions soient terminées

J'ai du mal à obtenir ma tête asynchrone / attente.

J'ai le code suivant qui appelle:

  • submitHandler() qui publie les entrées d'un formulaire dans des feuilles Google
async function onSubmit() {
                        setTimeout(() => {
                                submitHandler()
                                childRef.current.upload()
                        }, 1000)
                }
                //I want to wait for onSubmit to complete and then call another function which sets state and then launches a modal 
                
  • childRef.current.upload() qui publie un fichier sur S3 ...

mais je dois attendre les résultats de ces deux fonctions avant d'appeler une autre fonction pour ouvrir un modal et transmettre les résultats de ces deux fonctions.

Est-ce que quelqu'un peut m'aider s'il vous plaît?

Merci beaucoup

                const scriptURL =
                        'GOOGLE SCRIPT URL'
                const form = document.forms.emailform
                fetch(scriptURL, { method: 'POST', body: new FormData(form) })
                        .then(response => {
                                console.log('Success!', response)
                                setFormSuccess(1)
                        })
                        .catch(error => {
                                console.error('Error!', error.message)
                                setFormSuccess(2)
                        })
        } 

EDIT: Je dois mentionner dans la question originale que j'ai essayé d'attendre dans toutes les fonctions que j'appelle, mais aucune d'elles ne fonctionne


4 Réponses :


1
votes

Je pense que vous manquez juste quelques déclarations «en attente». J'ai également modifié le délai d'expiration.

    async submitHandler() {
            const scriptURL = 'GOOGLE SCRIPT URL'
            const form = document.forms.emailform
            try {
                let response = await fetch(scriptURL, { method: 'POST', body: new FormData(form) })
                console.log('Success!', response)
                setFormSuccess(1)
            } catch(error) {
                console.error('Error!', error.message)
                setFormSuccess(2)
            }
    } 

De plus, dans submitHandler (), vous n'utilisez pas correctement async-await. Vous utilisez les méthodes .then, qui ne peuvent pas être facilement combinées avec le fichier await.

async function onSubmit() {
                    let sleep = function (ms) {
                        return new Promise(resolve => setTimeout(resolve, ms))
                    }
                    await sleep(1000)
                    await submitHandler()
                    await childRef.current.upload()
            }
            //I want to wait for onSubmit to complete and then call another function which sets state and then launches a modal 
            

Si vous voulez toujours attraper des erreurs, vous devez encapsuler la récupération dans un bloc try.


7 commentaires

Merci désolé j'ai oublié de mentionner que l'attente submitHandler () donne une erreur qui attend n'est autorisée que dans les fonctions asynchrones


J'étais trop rapide, j'ai édité ma réponse. J'espère que cela aide :)


merci @kevin. Cela vient avec 'attendre' n'a aucun effet sur ce type d'expression


sur la fonction submitHandler (). J'ai ajouté cette fonction à la question maintenant


C'est un grand merci @kevin. Pourriez-vous me donner un guide sur le bloc de récupération pour l'équivalent de capture


@NickWild je l'ai ajouté à ma réponse. Je vous serais reconnaissant si vous pouviez marquer ma réponse comme acceptée si cela aidait :)


Brililant merci beaucoup @kevin. Je ne sais toujours pas si je fais ça mais ça résout mon problème et j'essaierai d'en savoir plus à ce sujet.



0
votes

Votre fonction doit renvoyer Promise . Alors retournez votre fetch()

async function onSubmit() {
                    setTimeout(() => {
                            const response = await submitHandler()
                            // Your response will be available here
                            console.log(response);
                            childRef.current.upload()
                    }, 1000)
            }

Donc à ta fonction principale tu pourrais

submitHeader(){
      const scriptURL =
                    'GOOGLE SCRIPT URL'
            const form = document.forms.emailform
           return fetch(scriptURL, { method: 'POST', body: new FormData(form) })
                    .then(response => {
                            console.log('Success!', response)
                            setFormSuccess(1)
                            return response;
                    })
                    .catch(error => {
                            console.error('Error!', error.message)
                            setFormSuccess(2)
                    })
    } 


5 commentaires

Merci, j'ai oublié de mentionner que j'avais essayé attendre sur toutes les fonctions et aucune d'elles ne fonctionnait. Je vais modifier ma question maintenant


mais il est important que votre fonction retourne attendre ne puisse être utilisée qu'avec Promise return.


La fonction de gestionnaire d'envoi publie dans un script google avec une récupération, puis capture ce changement d'état à ce moment-là et capture selon que la récupération est réussie ou non. Désolé d'être si stupide là-dessus! :-)


pourriez-vous montrer un extrait de code s'il vous plaît? Il m'est impossible de vous aider quand nous n'avons pas de réels retours de vos fonctions


Merci @Filip J'ai ajouté le code du submitHandler () à la question d'origine. S'il vous plaît laissez-moi savoir si vous avez besoin de quelque chose d'autre



0
votes

La première chose est que vous devez marquer le rappel de setTimeout comme async si vous voulez l' await intérieur.

Mais setTimeout utilise des callbacks et s'écarte ainsi du flux de contrôle souhaité. Ainsi, j'utiliserais un simple wrapper de promesse pour y arriver:

function onSubmit() {
  return promiseSetTimeout(async () => {
    await submitHandler();
    await childRef.current.upload();
  }, 1000);
}

Ainsi, vous pouvez attendre dessus et avoir le flux de contrôle souhaité.

const promiseSetTimeout = (cb, delay) => new Promise((resolve, reject) => {
  setTimeout(async () => {
    const ret = await cb();
    resolve(ret);
  }, delay);
});


6 commentaires

Merci @Vivick je reçois une promesseSetTimeout n'est pas défini


Vous avez copié l'implémentation que je vous ai donnée dans le même fichier (ou l'avez-vous importée si elle se trouve ailleurs)?


Merci oui Dans le même fichier - je viens de copier et coller. Il a également une erreur qui n'attend aucun effet sur ce type d'expression pour l'attente submitHandler ()


C'est probablement parce que ça ne rend pas une promesse


Merci d'avoir modifié la question pour inclure le submitHandler (). Des pensées?


Vous devez retourner votre appel pour fetch autre chose que cela devrait fonctionner correctement. Attendre quelque chose qui n'est pas vraiment attendu ne sera pas un problème



1
votes

Vous pouvez utiliser Promise.all () pour attendre plusieurs promesses, comme ceci

const result = await Promise.all([submitHandler(), childRef.current.upload()]);


1 commentaires

Merci @riwen. Bien que la réponse de Kevinkreps ait résolu mon problème, j'en ai également besoin pour attendre la deuxième fonction.