Différence entre asynchrone / wait et ES6 avec les générateurs

Je lisais juste cet article fantastique –

https://www.promisejs.org/generators/

et il met clairement en évidence cette fonction, qui est une fonction d’aide à la manipulation des fonctions du générateur:

function async(makeGenerator){ return function () { var generator = makeGenerator.apply(this, arguments); function handle(result){ // result => { done: [Boolean], value: [Object] } if (result.done) return Promise.resolve(result.value); return Promise.resolve(result.value).then(function (res){ return handle(generator.next(res)); }, function (err){ return handle(generator.throw(err)); }); } try { return handle(generator.next()); } catch (ex) { return Promise.reject(ex); } } } 

ce que je suppose est plus ou moins la façon dont le mot-clé async est implémenté avec async/await . Donc, la question est la suivante: si tel est le cas, quelle est la différence entre le mot-clé await et le mot-clé yield ? await toujours de transformer quelque chose en promesse, alors que le yield ne garantit pas une telle chose? C’est ma meilleure supposition!

Vous pouvez également voir comment async / waiting est similaire au rendement avec des générateurs dans cet article où il décrit la fonction “spawn”: https://jakearchibald.com/2014/es7-async-functions/

    yield peut être considéré comme l’élément constitutif de l’ await . yield prend la valeur donnée et la transmet à l’appelant. L’appelant peut alors faire ce qu’il veut avec cette valeur (1). Plus tard, l’appelant peut redonner une valeur au générateur (via generator.next() ) qui devient le résultat de l’expression de yield (2) ou une erreur qui apparaîtra comme étant l’expression de yield (3).

    asyncawait peut être considéré comme utilisant le yield . En (1) l’appelant (c.-à async . Le pilote asyncawait – similaire à la fonction que vous avez posté) encapsulera la valeur dans une promesse en utilisant un algorithme similaire à la new Promise(r => r(value) ( not not Promise.resolve , mais ce n’est pas un gros problème) .Il attend ensuite que la promesse soit résolue. Si elle se réalise, elle renvoie la valeur remplie à (2) .Si elle est rejetée, la raison de rejet est renvoyée comme une erreur à (3).

    Donc, l’utilité de l’ asyncawait est cette machine qui utilise du yield pour dérouler la valeur fournie comme une promesse et transmettre sa valeur résolue, en répétant jusqu’à ce que la fonction retourne sa valeur finale.

    Eh bien, il se trouve qu’il existe une relation très étroite entre async / wait et générateurs. Et je crois que async / waiting sera toujours construit sur des générateurs. Si vous regardez la façon dont Babel transpire async / attendez:

    Babel prend ceci:

     this.it('is a test', async function () { const foo = await 3; const bar = await new Promise(function (resolve) { resolve('7'); }); const baz = bar * foo; console.log(baz); }); 

    et le transforme en ceci

     function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; } this.it('is a test', _asyncToGenerator(function* () { // << now it's a generator const foo = yield 3; // << now it's yield not await const bar = yield new Promise(function (resolve) { resolve('7'); }); const baz = bar * foo; console.log(baz); })); 

    vous faites le calcul.

    Cela donne l'impression que le mot-clé asynchrone n'est que la fonction d'encapsulation, mais si c'est le cas, attendez-vous à ce qu'il devienne un rendement, il y aura probablement un peu plus de choses plus tard quand ils deviendront natifs.

    Quelle est la différence entre le mot-clé await et le mot-clé yield ?

    Le mot-clé await ne doit être utilisé que dans les async function s, alors que le mot-clé yield ne doit être utilisé que dans la function* générateur function* s. Et ceux-ci sont évidemment différents – l’un renvoie des promesses, l’autre des générateurs.

    await toujours de transformer quelque chose en promesse, alors que le yield ne garantit pas une telle chose?

    Oui, await appellera Promise.resolve sur la valeur attendue.

    yield ne donne que la valeur en dehors du générateur.

    Essayez ces programmes de test que j’avais l’habitude de comprendre en attente / async avec des promesses

    Programme n ° 1: sans promesses, il ne se déroule pas en séquence

     function functionA() { console.log('functionA called'); setTimeout(function() { console.log('functionA timeout called'); return 10; }, 15000); } function functionB(valueA) { console.log('functionB called'); setTimeout(function() { console.log('functionB timeout called = ' + valueA); return 20 + valueA; }, 10000); } function functionC(valueA, valueB) { console.log('functionC called'); setTimeout(function() { console.log('functionC timeout called = ' + valueA); return valueA + valueB; }, 10000); } async function executeAsyncTask() { const valueA = await functionA(); const valueB = await functionB(valueA); return functionC(valueA, valueB); } console.log('program started'); executeAsyncTask().then(function(response) { console.log('response called = ' + response); }); console.log('program ended'); 

    programme 2: avec des promesses:

     function functionA() { return new Promise((resolve, reject) => { console.log('functionA called'); setTimeout(function() { console.log('functionA timeout called'); // return 10; return resolve(10); }, 15000); }); } function functionB(valueA) { return new Promise((resolve, reject) => { console.log('functionB called'); setTimeout(function() { console.log('functionB timeout called = ' + valueA); return resolve(20 + valueA); }, 10000); }); } function functionC(valueA, valueB) { return new Promise((resolve, reject) => { console.log('functionC called'); setTimeout(function() { console.log('functionC timeout called = ' + valueA); return resolve(valueA + valueB); }, 10000); }); } async function executeAsyncTask() { const valueA = await functionA(); const valueB = await functionB(valueA); return functionC(valueA, valueB); } console.log('program started'); executeAsyncTask().then(function(response) { console.log('response called = ' + response); }); console.log('program ended'); 

    tldr;

    Utilisez Async / Await 99% du temps sur les générateurs. Pourquoi?

    1. Async / Await remplace directement les stream de travail les plus courants des chaînes de promesses, ce qui permet de déclarer le code comme s’il était synchrone, le simplifiant considérablement.

    2. Les générateurs décrivent le cas d’utilisation où vous appelleriez une série d’opérations asynchrones qui dépendent les unes des autres et qui finiront par être dans un état “terminé”. L’exemple le plus simple serait de parcourir les résultats qui renverraient le dernier ensemble, mais vous n’appeleriez une page que si nécessaire, pas immédiatement.

    3. Async / Await est en fait une abstraction construite au-dessus des générateurs pour faciliter le travail avec les promesses.

    Voir très en détail Explication d’Async / Await vs. Generators

    À bien des égards, les générateurs sont un sur-ensemble d’async / wait. En ce moment, async / waiting contient des traces de stack plus propres que co , la plus populaire des bibliothèques asynchrones / attendues. Vous pouvez implémenter votre propre saveur asynchrone / attendre en utilisant des générateurs et append de nouvelles fonctionnalités, comme la prise en charge intégrée du yield sur les non-promesses ou la construction sur des observables RxJS.

    Donc, en bref, les générateurs vous offrent plus de flexibilité et les bibliothèques basées sur des générateurs ont généralement plus de fonctionnalités. Mais asynchroniser / attendre est une partie essentielle du langage, il est standardisé et ne changera pas sous vous, et vous n’avez pas besoin d’une bibliothèque pour l’utiliser. J’ai un article de blog avec plus de détails sur la différence entre async / wait et générateurs.