Lors de l'utilisation d'un rappel simple comme dans l'exemple ci-dessous:
test() {
api.on( 'someEvent', function( response ) {
return response;
});
}
Comment la fonction peut-elle être modifiée pour utiliser asynchrone/wait? Spécifiquement, en supposant que «someEvent» soit garanti d'être appelé une fois et une fois seulement, j'aimerais que le test de fonction soit une fonction asynchrone qui ne retourne pas tant que le rappel n'est pas exécuté, tel que
async test() {
return await api.on( 'someEvent' );
}
async/await
n'est pas magique. Une fonction asynchrone est une fonction qui peut décompresser les promesses pour vous, vous aurez donc besoin de api.on()
pour 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 aussi des promesses elles-mêmes. Ainsi, vous n’obtiendrez pas la valeur de test()
, mais plutôt une promesse pour une valeur que vous pouvez utiliser comme suit:
async function whatever() {
// snip
const response = await test();
// use response here
// snip
}
Il est agaçant qu’il n’existe pas de solution simple et que l’emballage de return new Promise(...)
soit lamentable, mais j’ai trouvé une solution de contournement correcte en utilisant util.promisify
(en fait, il effectue également un peu l’emballage identique, mais en est plus joli).
function voidFunction(someArgs, callback) {
api.onActionwhichTakesTime(someMoreArgs, (response_we_need) => {
callback(null, response_we_need);
});
}
La fonction ci-dessus ne renvoie rien pour l'instant. Nous pouvons lui faire renvoyer une Promise
de la response
passée dans callback
en faisant:
const util = require('util');
const asyncFunction = util.promisify(voidFunction);
Maintenant, nous pouvons réellement await
la callback
.
async function test() {
return await asyncFunction(args);
}
Quelques règles lors de l'utilisation de util.promisify
callback
doit être le dernier argument de la fonction qui va être promisify
(err, res) => {...}
Ce qui est drôle, c’est que nous n’avons pas besoin d’écrire précisément en quoi consiste la callback
.
Vous pouvez y parvenir sans rappel, utilisez promesse async attendre au lieu de rappel ici. 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)'/>
async/wait est magique. Vous pouvez créer une fonction asPromise pour gérer ce type de situation:
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);
}
});
}
et ensuite l'utiliser quand vous voulez:
async test() {
return await this.asPromise(this,api.on,'someEvent' );
}
args nunmber sont des dynamiques.