2016-03-24 5 views
40

Ich war gerade diesen fantastischen Artikel lesen -Unterschied zwischen Asynchron/erwarten und ES6 Ausbeute mit Generatoren

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

und es unterstreicht eindeutig diese Funktion, die eine Hilfsfunktion für den Umgang mit Generator-Funktionen ist:

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); 
    } 
    } 
} 

was ich Hypothese ist mehr oder weniger die Art, wie das async-Schlüsselwort mit async/await implementiert wird. Also die Frage ist, wenn das der Fall ist, was zum Teufel ist der Unterschied zwischen dem await Schlüsselwort und dem yield Schlüsselwort? Macht await immer etwas zu einem Versprechen, während yield keine Garantie gibt? Das ist meine beste Schätzung!

Sie können auch sehen, wie async/await ähnlich ist mit Generatoren in diesem Artikel zu erhalten, wo er die ‚Spawn‘ Funktion beschreibt: https://jakearchibald.com/2014/es7-async-functions/

+1

asynchrone Funktion -> eine Coroutine. generator -> Iterator, der eine Coroutine verwendet, um seinen inneren Iterationsmechanismus zu verwalten. hunter horcht eine Coroutine aus, während yield ein Ergebnis aus einer Coroutine zurückgibt, die ein Generator verwendet: –

+1

'async/await' ist kein Teil von ES7. Bitte lesen Sie die Beschreibung des Tags. –

+0

@david haim, yeah aber async erwarten ist auf Generatoren gebaut, so dass sie nicht unterscheidbar –

Antwort

22

Nun, es stellt sich heraus, dass es eine sehr enge Beziehung zwischen Async/Warten und Generatoren gibt. Und ich glaube, Async/erwarten wird immer auf Generatoren gebaut werden. Wenn Sie die Art und Weise zu buchen Babel transpiles async/await:

Babel nimmt dies:

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); 

}); 

und verwandelt es in diesem

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); 
})); 

Sie die Mathematik zu tun.

Dadurch sieht es aus wie das async-Schlüsselwort ist nur diese Wrapper-Funktion, aber wenn das der Fall ist dann erwartet wird nur in Ausbeute, wird es wahrscheinlich ein bisschen mehr auf das Bild später, wenn sie native werden.

28

yield kann in Betracht gezogen werden, der Baustein der await sein. yield nimmt den angegebenen Wert und übergibt ihn an den Aufrufer. Der Anrufer kann dann mit diesem Wert tun, was er will (1). Später kann der Aufrufer dem Generator einen Wert zurückgeben (über generator.next()), der das Ergebnis des Ausdrucks yield (2) wird, oder ein Fehler, der scheinbar durch den Ausdruck yield (3) ausgelöst wird.

async - await kann in Betracht gezogen werden, yield zu verwenden. Bei (1) wird der Aufrufer (d. H. Der async - await Treiber - ähnlich wie die Funktion, die Sie gepostet haben) den Wert in ein Versprechen mit einem ähnlichen Algorithmus zu new Promise(r => r(value) (Hinweis, nichtPromise.resolve, aber das ist keine große Sache). Es wartet dann auf das Versprechen zu lösen. Wenn es erfüllt ist, übergibt es den erfüllten Wert zurück an (2). Wenn es abgelehnt wird, wird der Ablehnungsgrund als Fehler bei (3) ausgegeben.

So ist die Nützlichkeit von async-await ist diese Maschinen, die yield den ergab Wert als ein Versprechen auszupacken verwendet und seine aufgelöst Wert zurück übergeben, zu wiederholen, bis die Funktion seiner endgültigen Wert zurückgibt.

20

Was zum Teufel ist der Unterschied zwischen dem Schlüsselwort await und dem Schlüsselwort yield?

await Das Schlüsselwort wird nur in async function s verwendet werden, während das yield Schlüsselwort nur in Generator function* s verwendet werden soll. Und diese sind natürlich auch anders - der eine gibt Versprechen, der andere gibt Generatoren zurück.

Macht await immer etwas zu einem Versprechen, während yield keine Garantie gibt?

Ja, await werden Promise.resolve auf dem erwarteten Wert nennen.

yield ergibt nur den Wert außerhalb des Generators.

+0

A minor nit, aber wie ich in meiner Antwort erwähnt die Spezifikation verwendet nicht Promise.resolve (früher verwendet), es verwendet PromiseCapability :: resolve, die genauer durch den Promise-Konstruktor dargestellt wird. – Arnavion

+0

@Arnavion: ['Promise.resolve'] (http://www.ecma-international.org/ecma-262/6.0/#sec-promise.resolve) verwendet genau die gleiche' neue PromiseCapability (% Promise%) ' dass die async/html-Spezifikation direkt verwendet, ich dachte nur, 'Promise.resolve' ist besser zu verstehen. – Bergi

+1

'Promise.resolve' hat einen zusätzlichen" IsPromise == true? Then return self value "Kurzschluss, den async nicht hat. Das heißt, "erwarten p", wo "p" eine Verheißung ist, wird eine neue Zusage zurückgeben, die zu "p" verrechnet wird, während "Promise.resolve (p)" "p" zurückgeben würde. – Arnavion

Verwandte Themen