Comment "attendre" le retour d'un rappel?

Lors de l'utilisation d'un simple rappel comme dans l'exemple ci-dessous:

test() {
  api.on( 'someEvent', function( response ) {
    return response;
  });
}

comment modifier la fonction pour utiliser async / en attente? Plus précisément, en supposant que "someEvent" est garanti pour être appelé une fois et une seule fois, je voudrais que le test de fonction soit une fonction async qui ne retourne pas jusqu'à ce que le rappel soit exécuté tel que:

async test() {
  return await api.on( 'someEvent' );
}
37
demandé sur estus 2016-05-08 22:56:17

2 réponses

async/await n'est pas magique. Une fonction async est une fonction qui peut déballer des promesses pour vous, vous aurez donc besoin de api.on() pour rendre une promesse pour que ça marche. Quelque chose comme ceci:

function apiOn(event) {
  return new Promise(resolve => {
    api.on(event, response => resolve(response));
  });
}

async function test() {
  return await apiOn( 'someEvent' ); // await is actually optional here
                                      // you'd return a Promise either way.
}

mais c'est un mensonge aussi, parce que les fonctions async rendent aussi les promesses elles-mêmes, donc vous n'allez pas réellement retirer la valeur de 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
}
55
répondu Madara Uchiha 2017-09-01 11:49:53

c'est agaçant qu'il n'y ait pas de solution simple, et emballer return new Promise(...) est moche, mais j'ai trouvé un ok de travail autour de l'aide de util.promisify (en fait, elle aussi un peu le même emballage, juste l'air plus sympa).

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 le faire revenir a Promiseresponse passé callback en faisant:

const util = require('util');

const asyncFunction = util.promisify(voidFunction);

Maintenant, nous pouvons effectivement awaitcallback.

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 être promisify
  • soi-disant de rappel doit être de la forme (err, res) => {...}

ce qui est drôle, c'est que nous n'avons pas besoin d'écrire spécifiquement ce qui est le callback en fait si.

0
répondu ErikD 2018-09-13 08:42:23