Bei Verwendung eines einfachen Rückrufs wie im folgenden Beispiel:
test() {
api.on( 'someEvent', function( response ) {
return response;
});
}
Wie kann die Funktion geändert werden, um async/await zu verwenden? Unter der Annahme, dass "someEvent" garantiert einmal und nur einmal aufgerufen wird, möchte ich, dass es sich bei der Funktion test um eine async-Funktion handelt, die erst zurückkehrt, wenn der Rückruf ausgeführt wird.
async test() {
return await api.on( 'someEvent' );
}
async/await
ist keine Zauberei. Eine asynchrone Funktion ist eine Funktion, mit der Sie Promises auspacken können. Sie müssen also api.on()
verwenden, um ein Promise zurückzusenden. Etwas wie das:
function apiOn(event) {
return new Promise(resolve => {
api.on(event, response => resolve(response));
});
}
Dann
async function test() {
return await apiOn( 'someEvent' ); // await is actually optional here
// you'd return a Promise either way.
}
Aber das ist auch eine Lüge, weil asynchrone Funktionen auch Promises selbst zurückgeben, so dass Sie nicht wirklich den Wert aus test()
bekommen, sondern ein Promise für einen Wert, den Sie wie folgt verwenden können:
async function whatever() {
// snip
const response = await test();
// use response here
// snip
}
Es ist ärgerlich, dass es keine unkomplizierte Lösung gibt, und return new Promise(...)
zu verpacken ist schwer, aber ich habe mit util.promisify
eine Umgehung gefunden.
function voidFunction(someArgs, callback) {
api.onActionwhichTakesTime(someMoreArgs, (response_we_need) => {
callback(null, response_we_need);
});
}
Die obige Funktion gibt noch nichts zurück. Wir können eine Promise
der in response
übergebenen callback
zurückgeben, indem Sie
const util = require('util');
const asyncFunction = util.promisify(voidFunction);
Jetzt können wir await
die callback
.
async function test() {
return await asyncFunction(args);
}
Einige Regeln bei der Verwendung von util.promisify
callback
muss das letzte Argument der Funktion sein, die promisify
sein wird.(err, res) => {...}
sein.Das Witzige daran ist, dass wir nie genau schreiben müssen, was die callback
eigentlich ist.
Sie können dies ohne Rückrufe erreichen, verwenden Sie hier asiseing asise warten anstelle von Rückrufen, wie ich dies tun würde. Und auch hier habe ich zwei Methoden dargestellt, um Fehler zu behandeln
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/await ist magisch. Sie können eine Funktion asPromise erstellen, um mit diesen Situationen umzugehen:
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);
}
});
}
und benutze es dann, wenn du willst:
async test() {
return await this.asPromise(this,api.on,'someEvent' );
}
argumente sind Dynamik.