Lors de l'utilisation d'un simple rappel comme dans l'exemple ci-dessous:
test() {
api.on( 'someEvent', function( response ) {
return response;
});
}
Comment la fonction peut-elle être modifiée pour utiliser async / await? Plus précisément, en supposant que `` someEvent '' soit appelé une et une seule fois, j'aimerais que le test de fonction soit une fonction asynchrone qui ne retourne pas tant que le rappel n'est pas exécuté, par exemple:
async test() {
return await api.on( 'someEvent' );
}
Réponses:
async/await
n'est pas magique. Une fonction asynchrone est une fonction qui peut dérouler des promesses pour vous, vous devrezapi.on()
donc renvoyer une promesse pour que cela fonctionne. Quelque chose comme ça:function apiOn(event) { return new Promise(resolve => { api.on(event, response => resolve(response)); }); }
ensuite
async function test() { return await apiOn( 'someEvent' ); // await is actually optional here // you'd return a Promise either way. }
Mais c'est aussi un mensonge, car les fonctions asynchrones renvoient également des promesses elles-mêmes, vous n'allez donc pas en tirer la valeur
test()
, mais plutôt une promesse pour une valeur, que vous pouvez utiliser comme ceci:async function whatever() { // snip const response = await test(); // use response here // snip }
la source
const apiOn = (event) => new Promise(resolve => api.on(event, resolve));
C'est ennuyeux qu'il n'y ait pas de solution simple, et l'emballage
return new Promise(...)
est difficile, mais j'ai trouvé un moyen de contourner le problèmeutil.promisify
(en fait, il fait aussi un peu le même emballage, c'est juste plus joli).function voidFunction(someArgs, callback) { api.onActionwhichTakesTime(someMoreArgs, (response_we_need) => { callback(null, response_we_need); }); }
La fonction ci-dessus ne renvoie encore rien. On peut lui faire retourner un
Promise
duresponse
passé encallback
faisant:const util = require('util'); const asyncFunction = util.promisify(voidFunction);
Maintenant, nous pouvons réellement
await
lecallback
.async function test() { return await asyncFunction(args); }
Quelques règles lors de l'utilisation
util.promisify
callback
doit être le dernier argument de la fonction qui va êtrepromisify
(err, res) => {...}
Ce qui est drôle, c'est que nous n'avons jamais besoin d'écrire spécifiquement ce
callback
qui est réellement.la source
async / await est magique. Vous pouvez créer une fonction
asPromise
pour gérer ce genre de situations:function asPromise(context, callbackFunction, ...args) { return new Promise((resolve, reject) => { args.push((err, data) => { if (err) { reject(err); } else { resolve(data); } }); if (context) { callbackFunction.call(context, ...args); } else { callbackFunction(...args); } }); }
puis utilisez-le quand vous le souhaitez:
async test() { return await this.asPromise(this, api.on, 'someEvent'); }
le nombre d'arguments est variable.
la source
Vous pouvez y parvenir sans callback, utilisez promise async await au lieu de callbacks ici comment je le ferais. Et aussi ici j'ai illustré deux méthodes pour gérer les erreurs
clickMe = async (value) => { // begin to wait till the message gets here; let {message, error} = await getMessage(value); // if error is not null if(error) return console.log('error occured ' + error); return console.log('message ' + message); } getMessage = (value) => { //returning a promise return new Promise((resolve, reject) => { setTimeout(() => { // if passed value is 1 then it is a success if(value == 1){ resolve({message: "**success**", error: null}); }else if (value == 2){ resolve({message: null, error: "**error**"}); } }, 1000); }); } clickWithTryCatch = async (value) => { try{ //since promise reject in getMessage2 let message = await getMessage2(value); console.log('message is ' + message); }catch(e){ //catching rejects from the promise console.log('error captured ' + e); } } getMessage2 = (value) => { return new Promise((resolve, reject) => { setTimeout(() => { if(value == 1) resolve('**success**'); else if(value == 2) reject('**error**'); }, 1000); }); }
<input type='button' value='click to trigger for a value' onclick='clickMe(1)' /> <br/> <input type='button' value='click to trigger an error' onclick='clickMe(2)' /> <br/> <input type='button' value='handling errors with try catch' onclick='clickWithTryCatch(1)'/> <br/> <input type='button' value='handling errors with try catch' onclick='clickWithTryCatch(2)'/>
la source