Asynchrone JavaScript-programmering: beloften versus generatoren

Met beloften en generatoren kun je asynchrone code schrijven. Ik begrijp niet waarom beide mechanismen zijn geïntroduceerd in ECMA-script 6. Wanneer kan ik de beloften het beste gebruiken en wanneer de generatoren?


Antwoord 1, autoriteit 100%

Er is geen tegenstelling tussen deze twee technieken: ze bestaan ​​naast elkaar en vullen elkaar mooi aan.

Met

Beloftenkunt u het resultaat krijgen van een asynchrone bewerking die nogniet beschikbaar is.
Het lost het Pyramid of Doom-probleem op. Dus in plaats van:

function ourImportantFunction(callback) {
  //... some code 1
  task1(function(val1) {
    //... some code 2
    task2(val1, function(val2) {
      //... some code 3
      task3(val2, callback);
    });
  });
}

je kunt schrijven:

function ourImportantFunction() {
  return Promise.resolve()
    .then(function() {
        //... some code 1
        return task1(val3)
    })
    .then(function(val2) {
        //... some code 2
        return task2(val2)
    })
    .then(function(val2) {
        //... some code 3
        return task3(val2);
    });
}
ourImportantFunction().then(callback);

Maar zelfs met beloftes moet je code op asynchrone manier schrijven – je moet altijd callbacks doorgeven aan de functies.
Het schrijven van asynchrone code is veel moeilijker dan synchroon. Zelfs met beloften, wanneer de code enorm is, wordt het moeilijk om het algoritme te zien (het is erg subjectief, maar voor de meeste programmeurs denk ik dat het waar is).

Dus we willen asynchrone code synchroon schrijven. Dat is waar generatorenons komen helpen.
In plaats van de bovenstaande code kun je schrijven:

var ourImportantFunction = spawn(function*() {
    //... some code 1
    var val1 = yield task1();
    //... some code 2
    var val2 = yield task2(val1);
    //... some code 3
    var val3 = yield task3(val2);
    return val3;
});
ourImportantFunction().then(callback);

waar de eenvoudigst mogelijke spawnrealisatie zoiets kan zijn als:

function spawn(generator) {
  return function() {    
    var iter = generator.apply(this, arguments);
    return Promise.resolve().then(function onValue(lastValue){
      var result = iter.next(lastValue); 
      var done  = result.done;
      var value = result.value;
      if (done) return value; // generator done, resolve promise
      return Promise.resolve(value).then(onValue, iter.throw.bind(iter)); // repeat
    });
  };
}

Zoals je kunt zien, moet value(resultaat van een asynchrone functie task{N}) een belofte zijn. Je kunt dit niet doen met terugbellen.

Wat nog moet gebeuren is de spawntechniek in de taal zelf te implementeren. Dus vervangen we spawndoor asyncen yielddoor awaiten komen naar ES7 async/await:

var ourImportantFunction = async function() {
    //... some code 1
    var val1 = await task1();
    //... some code 2
    var val2 = await task2(val1);
    //... some code 3
    var val3 = await task3(val2);
    return val3;
}

Ik raad je aan om deze videote bekijken om meer te weten te komen over deze en andere komende technieken.
Hint:Als de man te snel voor je spreekt, vertraag dan de speelsnelheid (“instellingen” in de rechter benedenhoek, of druk gewoon op [shift+ <] ;])

Wat is het beste:alleen terugbellen, of beloften, of beloften met generatoren – dit is een zeer subjectieve vraag.
Terugbellen is op dit moment de snelst mogelijke oplossing (de prestaties van native beloften zijn nu erg slecht). Beloften met generatoren geven u de mogelijkheid om asynchrone code synchroon te schrijven. Maar voor nu zijn ze veel langzamer dan eenvoudige callbacks.


Antwoord 2, autoriteit 12%

Beloften en generatoren zijn verschillende softwarepatronen (constructies):

  1. http://en.wikipedia.org/wiki/Futures_and_promises
  2. http://en.wikipedia.org/wiki/Generator_(computer_programming)

In feite zijn generatoren niet asynchroon.

Generators zijn handig wanneer u een reeks waarden niet in één keer, maar één per vraag wilt ophalen. Generator zal de volgende waarde onmiddellijk (synchroon) retourneren bij elke oproep totdat deze het einde van de reeks bereikt (of eindeloos in het geval van oneindige reeksen).

Beloftes zijn handig wanneer u de waarde moet “uitstellen”, die mogelijk nog niet is berekend (of mogelijk nog niet beschikbaar is). Als de waarde beschikbaar is, is het de hele waarde (geen deel ervan), zelfs als het een array of een andere complexe waarde is.

Je kunt meer details en voorbeelden zien in wikipedia-artikelen.

Other episodes