Vraag Hoe retourneer ik het antwoord van een asynchrone oproep?


Ik heb een functie foo die een Ajax-aanvraag doet. Hoe kan ik het antwoord terugsturen foo?

Ik probeerde de waarde terug te geven van de success callback evenals het toewijzen van het antwoord aan een lokale variabele in de functie en die terug te zetten, maar geen van die manieren retourneert het antwoord.

function foo() {
    var result;

    $.ajax({
        url: '...',
        success: function(response) {
            result = response;
            // return response; // <- I tried that one as well
        }
    });

    return result;
}

var result = foo(); // It always ends up being `undefined`.

4307
2018-01-08 17:06


oorsprong


antwoorden:


-> Zie voor een meer algemene uitleg over async-gedrag met verschillende voorbeelden  Waarom wordt mijn variabele ongewijzigd nadat ik hem in een functie heb gewijzigd? - Asynchrone codereferentie 

-> Als u het probleem al begrijpt, kunt u de mogelijke oplossingen hieronder overslaan.

Het probleem

De EEN in Ajax betekent asynchrone . Dat betekent dat het verzenden van het verzoek (of liever het ontvangen van het antwoord) uit de normale uitvoeringsstroom wordt gehaald. In jouw voorbeeld $.ajax keert onmiddellijk terug en de volgende verklaring, return result;, wordt uitgevoerd vóór de functie die u hebt gepasseerd als success callback werd zelfs gebeld.

Hier is een analogie die hopelijk het verschil maakt tussen synchrone en asynchrone stroomopname:

synchrone

Stel je voor dat je een vriend belt en hem vraagt ​​iets voor je op te zoeken. Hoewel het even kan duren, wacht je aan de telefoon en staar je in de ruimte, totdat je vriend je het antwoord geeft dat je nodig hebt.

Hetzelfde gebeurt wanneer u een functieaanroep plaatst met "normale" code:

function findItem() {
    var item;
    while(item_not_found) {
        // search
    }
    return item;
}

var item = findItem();

// Do something with item
doSomethingElse();

Hoewel findItem kan lang duren om uit te voeren, elke code die daarna komt var item = findItem(); moet Wacht totdat de functie het resultaat retourneert.

Asynchronous

Je belt je vriend opnieuw om dezelfde reden. Maar deze keer zeg je hem dat je haast hebt en hij zou moeten bel je terug op je mobiele telefoon. Je hangt op, gaat het huis uit en doet wat je van plan was te doen. Als je vriend je terugbelt, heb je te maken met de informatie die hij je heeft gegeven.

Dat is precies wat er gebeurt als je een Ajax-aanvraag doet.

findItem(function(item) {
    // Do something with item
});
doSomethingElse();

In plaats van te wachten op de reactie, wordt de uitvoering onmiddellijk voortgezet en wordt de instructie na de Ajax-oproep uitgevoerd. Om het antwoord uiteindelijk te krijgen, geeft u een functie op die moet worden aangeroepen zodra het antwoord is ontvangen, een Bel terug (let op iets? Bel terug ?). Elke instructie die na die oproep binnenkomt, wordt uitgevoerd voordat de callback wordt aangeroepen.


Oplossingen)

Omarm het asynchrone karakter van JavaScript! Hoewel bepaalde asynchrone bewerkingen synchrone tegenhangers leveren (net als "Ajax"), is het over het algemeen afgeraden om ze te gebruiken, vooral in een browsercontext.

Waarom is het slecht, vraag je dat?

JavaScript wordt uitgevoerd in de UI-thread van de browser en een langdurig proces blokkeert de gebruikersinterface, waardoor deze niet meer reageert. Bovendien is er een bovengrens voor de uitvoeringstijd voor JavaScript en de browser zal de gebruiker vragen of de uitvoering moet worden voortgezet of niet.

Dit is allemaal een slechte gebruikerservaring. De gebruiker kan niet zien of alles goed werkt of niet. Bovendien zal het effect slechter zijn voor gebruikers met een trage verbinding.

In het volgende zullen we kijken naar drie verschillende oplossingen die allemaal op elkaar zijn gebouwd:

  • Beloften met async/await (ES2017 +, beschikbaar in oudere browsers als u een transponder of regenerator gebruikt)
  • callbacks (populair in knoop)
  • Beloften met then() (ES2015 +, beschikbaar in oudere browsers als u een van de vele beloofde bibliotheken gebruikt)

Alle drie zijn beschikbaar in de huidige browsers en knooppunt 7+. 


ES2017 +: beloftes met async/await

De nieuwe ECMAScript-versie die in 2017 werd uitgebracht, werd geïntroduceerd syntax-niveau ondersteuning voor asynchrone functies. Met de hulp van async en await, u kunt asynchroon schrijven in een "synchrone stijl". Vergis je echter niet: de code is nog steeds asynchroon, maar het is gemakkelijker om te lezen / begrijpen.

async/await bouwt voort op de beloften: een async functie retourneert altijd een belofte. await "ontgrendelt" een belofte en resulteert ofwel in de waarde waarmee de belofte is opgelost of geeft een fout als de belofte werd afgewezen.

Belangrijk: Je kunt alleen gebruiken await in een async functie. Dat betekent dat je op het allerhoogste niveau nog steeds direct met de belofte moet werken.

U kunt meer lezen over async en await op MDN.

Hier is een voorbeeld dat voortborduurt op de bovenstaande vertraging:

// Using 'superagent' which will return a promise.
var superagent = require('superagent')

// This is isn't declared as `async` because it already returns a promise
function delay() {
  // `delay` returns a promise
  return new Promise(function(resolve, reject) {
    // Only `delay` is able to resolve or reject the promise
    setTimeout(function() {
      resolve(42); // After 3 seconds, resolve the promise with value 42
    }, 3000);
  });
}


async function getAllBooks() {
  try {
    // GET a list of book IDs of the current user
    var bookIDs = await superagent.get('/user/books');
    // wait for a second (just for the sake of this example)
    await delay(1000);
    // GET information about each book
    return await superagent.get('/books/ids='+JSON.stringify(bookIDs));
  } catch(error) {
    // If any of the awaited promises was rejected, this catch block
    // would catch the rejection reason
    return null;
  }
}

// Async functions always return a promise
getAllBooks()
  .then(function(books) {
    console.log(books);
  });

nieuwer browser en knooppunt versies ondersteuning async/await. U kunt ook oudere omgevingen ondersteunen door uw code te transformeren naar ES5 met behulp van regenerator (of hulpprogramma's die regenerator gebruiken, zoals Babel).


Laat functies accepteren callbacks

Een terugbellen is gewoon een functie die wordt doorgegeven aan een andere functie. Die andere functie kan de functie doorgeven wanneer deze gereed is. In de context van een asynchroon proces wordt de callback aangeroepen wanneer het asynchrone proces is voltooid. Meestal wordt het resultaat doorgegeven aan de callback.

In het voorbeeld van de vraag kunt u maken foo accepteer een callback en gebruik deze als success Bel terug. Dus dit

var result = foo();
// Code that depends on 'result'

wordt

foo(function(result) {
    // Code that depends on 'result'
});

Hier hebben we de functie "inline" gedefinieerd, maar u kunt elke functie-verwijzing passeren:

function myCallback(result) {
    // Code that depends on 'result'
}

foo(myCallback);

foo zelf is als volgt gedefinieerd:

function foo(callback) {
    $.ajax({
        // ...
        success: callback
    });
}

callback verwijst naar de functie waarnaar we gaan foo wanneer we het noemen en we geven het gewoon door aan success. D.w.z. zodra het Ajax-verzoek succesvol is, $.ajax zal bellen callback en geef het antwoord door aan de callback (waarnaar kan worden verwezen met result, omdat dit de manier is waarop we de callback hebben gedefinieerd).

U kunt het antwoord ook verwerken voordat u het doorgeeft aan de callback:

function foo(callback) {
    $.ajax({
        // ...
        success: function(response) {
            // For example, filter the response
            callback(filtered_response);
        }
    });
}

Het is gemakkelijker om code te schrijven met behulp van callbacks dan het lijkt. In de browser is JavaScript immers sterk afhankelijk van gebeurtenissen (DOM-gebeurtenissen). Het ontvangen van het Ajax-antwoord is niets anders dan een evenement.
Er kunnen zich problemen voordoen wanneer u met code van derden moet werken, maar de meeste problemen kunnen worden opgelost door alleen de applicatiestroom door te nemen.


ES2015 +: beloftes met dan()

De Promise API is een nieuw kenmerk van ECMAScript 6 (ES2015), maar het is goed browser ondersteuning nu al. Er zijn ook veel bibliotheken die de standaard Promises API implementeren en aanvullende methoden bieden om het gebruik en de samenstelling van asynchrone functies (bijv. blauwe vogel).

Beloften zijn containers voor toekomst waarden. Wanneer de belofte de waarde ontvangt (het is opgelost) of wanneer het is geannuleerd (verworpen), meldt dit al zijn "luisteraars" die toegang tot deze waarde willen hebben.

Het voordeel ten opzichte van eenvoudige callbacks is dat ze u toestaan ​​om uw code te ontkoppelen en ze zijn gemakkelijker te componeren.

Hier is een eenvoudig voorbeeld van het gebruik van een belofte:

function delay() {
  // `delay` returns a promise
  return new Promise(function(resolve, reject) {
    // Only `delay` is able to resolve or reject the promise
    setTimeout(function() {
      resolve(42); // After 3 seconds, resolve the promise with value 42
    }, 3000);
  });
}

delay()
  .then(function(v) { // `delay` returns a promise
    console.log(v); // Log the value once it is resolved
  })
  .catch(function(v) {
    // Or do something else if it is rejected 
    // (it would not happen in this example, since `reject` is not called).
  });

Toegepast op onze Ajax-oproep kunnen we beloftes als deze gebruiken:

function ajax(url) {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
      resolve(this.responseText);
    };
    xhr.onerror = reject;
    xhr.open('GET', url);
    xhr.send();
  });
}

ajax("/echo/json")
  .then(function(result) {
    // Code depending on result
  })
  .catch(function() {
    // An error occurred
  });

Het beschrijven van alle voordelen die belofte bieden, valt buiten het bestek van dit antwoord, maar als je nieuwe code schrijft, moet je ze serieus overwegen. Ze bieden een grote abstractie en scheiding van uw code.

Meer informatie over beloften: HTML5 rocks - JavaScript-beloften

Kanttekening: de uitgestelde objecten van jQuery

Uitgestelde objecten zijn jQuery's aangepaste implementatie van beloften (voordat de Promise API werd gestandaardiseerd). Ze gedragen zich bijna als beloftes, maar stellen een iets andere API bloot.

Elke Ajax-methode van jQuery retourneert al een "uitgesteld object" (eigenlijk een belofte van een uitgesteld object) die je net kunt retourneren vanuit je functie:

function ajax() {
    return $.ajax(...);
}

ajax().done(function(result) {
    // Code depending on result
}).fail(function() {
    // An error occurred
});

Kanttekening: Beloof gotchas

Houd er rekening mee dat beloften en uitgestelde objecten rechtvaardig zijn containers voor een toekomstige waarde zijn ze niet de waarde zelf. Stel dat u het volgende had:

function checkPassword() {
    return $.ajax({
        url: '/password',
        data: {
            username: $('#username').val(),
            password: $('#password').val()
        },
        type: 'POST',
        dataType: 'json'
    });
}

if (checkPassword()) {
    // Tell the user they're logged in
}

Deze code begrijpt de bovenstaande asynchronisatieproblemen verkeerd. In het bijzonder, $.ajax() bevriest de code niet terwijl deze de '/ wachtwoord' pagina op uw server controleert - het verzendt een verzoek naar de server en retourneert onmiddellijk een jQuery Ajax Uitgesteld object, niet het antwoord van de server. Dat betekent het if verklaring krijgt altijd dit uitgestelde object, behandel het als true, en ga door alsof de gebruiker is ingelogd. Niet goed.

Maar de oplossing is eenvoudig:

checkPassword()
.done(function(r) {
    if (r) {
        // Tell the user they're logged in
    } else {
        // Tell the user their password was bad
    }
})
.fail(function(x) {
    // Tell the user something bad happened
});

Niet aan te raden: synchrone 'Ajax'-oproepen

Zoals ik al zei, sommige (!) Asynchrone operaties hebben synchrone tegenhangers. Ik pleit niet voor hun gebruik, maar omwille van de volledigheid, hier is hoe u een synchrone aanroep zou doen:

Zonder jQuery

Als u direct een XMLHTTPRequest object, pass false als derde argument voor .open.

jQuery

Als je gebruikt jQuery, u kunt de async optie om false. Merk op dat deze optie is verouderd sinds jQuery 1.8. Je kunt dan nog steeds een gebruiken success terugbellen of toegang tot de responseText eigendom van de jqXHR-object:

function foo() {
    var jqXHR = $.ajax({
        //...
        async: false
    });
    return jqXHR.responseText;
}

Als u een andere jQuery Ajax-methode gebruikt, zoals $.get, $.getJSON, etc., je moet het veranderen naar $.ajax(aangezien u alleen configuratieparameters kunt doorgeven aan $.ajax).

Kom op! Het is niet mogelijk om een ​​synchrone te maken JSONP verzoek. JSONP is van nature asynchroon (een reden te meer om deze optie niet eens te overwegen).


4654
2018-01-08 17:06



Als je niet gebruik van jQuery in uw code, dit antwoord is voor u

Uw code zou iets in de trant van dit moeten zijn:

function foo() {
    var httpRequest = new XMLHttpRequest();
    httpRequest.open('GET', "/echo/json");
    httpRequest.send();
    return httpRequest.responseText;
}

var result = foo(); // always ends up being 'undefined'

Felix Kling heeft het prima gedaan om een ​​antwoord te schrijven voor mensen die jQuery gebruiken voor AJAX, ik heb besloten om een ​​alternatief te bieden voor mensen die dat niet zijn.

(Let op, voor degenen die het nieuwe gebruiken fetch API, Angular of belooft dat ik hieronder een ander antwoord heb toegevoegd)


Waar je voor staat

Dit is een korte samenvatting van "Uitleg van het probleem" van het andere antwoord, als je niet zeker bent nadat je dit hebt gelezen, lees dat.

De EEN in AJAX staat voor asynchrone. Dat betekent dat het verzenden van het verzoek (of liever het ontvangen van het antwoord) uit de normale uitvoeringsstroom wordt gehaald. In jouw voorbeeld .send keert onmiddellijk terug en de volgende verklaring, return result;, wordt uitgevoerd vóór de functie die u hebt gepasseerd als success callback werd zelfs gebeld.

Dit betekent dat als je terugkeert, de luisteraar die je hebt gedefinieerd nog niet is uitgevoerd, wat betekent dat de waarde die je terugkeert niet is gedefinieerd.

Hier is een eenvoudige analogie

function getFive(){ 
    var a;
    setTimeout(function(){
         a=5;
    },10);
    return a;
}

(Viool)

De waarde van a teruggegeven is undefined sinds de a=5 deel is nog niet uitgevoerd. AJAX gedraagt ​​zich als volgt, u geeft de waarde terug voordat de server de kans kreeg om uw browser te vertellen wat die waarde is.

Een mogelijke oplossing voor dit probleem is coderen re-actief , vertel je programma wat je moet doen als de berekening is voltooid.

function onComplete(a){ // When the code completes, do this
    alert(a);
}

function getFive(whenDone){ 
    var a;
    setTimeout(function(){
         a=5;
         whenDone(a);
    },10);
}

Dit heet CPS. Kortom, we zijn voorbij getFive een actie die uitgevoerd moet worden wanneer deze voltooid is, we vertellen onze code hoe te reageren wanneer een evenement voltooid is (zoals onze AJAX-oproep, of in dit geval de time-out).

Gebruik zou zijn:

getFive(onComplete);

Die "5" op het scherm moet melden. (Viool).

Mogelijke oplossingen

Er zijn in principe twee manieren om dit op te lossen:

  1. Maak de AJAX-oproep synchroon (laat hem SJAX noemen).
  2. Herstructureer uw code zodat deze correct werkt met callbacks.

1. Synchrone AJAX - Doe het niet !!

Wat betreft synchrone AJAX, doe het niet! Het antwoord van Felix werpt enkele overtuigende argumenten op waarom het een slecht idee is. Om het samen te vatten, het bevriest de browser van de gebruiker totdat de server het antwoord retourneert en een zeer slechte gebruikerservaring creëert. Hier is nog een korte samenvatting van MDN over waarom:

XMLHttpRequest ondersteunt zowel synchrone als asynchrone communicatie. In het algemeen moeten asynchrone verzoeken echter om synchrone redenen de voorkeur hebben boven synchrone verzoeken.

Kortom, synchrone verzoeken blokkeren de uitvoering van code ... ... dit kan serieuze problemen veroorzaken ...

als jij hebben om het te doen, kun je een vlag passeren: Hier is hoe:

var request = new XMLHttpRequest();
request.open('GET', 'yourURL', false);  // `false` makes the request synchronous
request.send(null);

if (request.status === 200) {// That's HTTP for 'ok'
  console.log(request.responseText);
}

2. Herstructureringscode

Laat uw functie een terugroep accepteren. In de voorbeeldcode foo kan een callback worden geaccepteerd. We zullen onze code vertellen hoe Reageer wanneer foo voltooit.

Zo:

var result = foo();
// code that depends on `result` goes here

Wordt:

foo(function(result) {
    // code that depends on `result`
});

Hier passeerden we een anonieme functie, maar we konden net zo goed een verwijzing naar een bestaande functie doorgeven, waardoor het eruit zag als:

function myHandler(result) {
    // code that depends on `result`
}
foo(myHandler);

Raadpleeg het antwoord van Felix voor meer informatie over hoe dit callback-ontwerp wordt uitgevoerd.

Laten we nu foo zelf definiëren om dienovereenkomstig te handelen

function foo(callback) {
    var httpRequest = new XMLHttpRequest();
    httpRequest.onload = function(){ // when the request is loaded
       callback(httpRequest.responseText);// we're calling our method
    };
    httpRequest.open('GET', "/echo/json");
    httpRequest.send();
}

(viool)

We hebben nu onze foo-functie een actie laten uitvoeren die wordt uitgevoerd wanneer de AJAX met succes wordt voltooid, we kunnen dit verder uitbreiden door te controleren of de responsstatus niet 200 is en dienovereenkomstig te handelen (maak een failhandler en dergelijke aan). Ons probleem effectief oplossen.

Als je dit nog steeds moeilijk begrijpt lees de AJAX-handleiding Aan de slag bij MDN.


886
2018-05-29 23:30



XMLHttpRequest 2 (lees eerst de antwoorden van Benjamin Gruenbaum & Felix Kling)

Als u jQuery niet gebruikt en een mooie korte XMLHttpRequest 2 wilt die werkt in de moderne browsers en ook in de mobiele browsers, raad ik aan het op deze manier te gebruiken:

function ajax(a, b, c){ // URL, callback, just a placeholder
  c = new XMLHttpRequest;
  c.open('GET', a);
  c.onload = b;
  c.send()
}

Zoals je kan zien:

  1. Het is korter dan alle andere functies in de lijst.
  2. De callback wordt direct ingesteld (dus geen extra onnodige sluitingen).
  3. Het gebruikt de nieuwe onload (u hoeft dus niet te controleren op readystate && status)
  4. Er zijn een aantal andere situaties die ik me niet herinner en die het XMLHttpRequest 1 vervelend maken.

Er zijn twee manieren om de respons van deze Ajax-oproep te krijgen (drie met de naam XMLHttpRequest var):

De makkelijkste:

this.response

Of als u om wat voor reden dan ook bind() het terugbellen naar een klas:

e.target.response

Voorbeeld:

function callback(e){
  console.log(this.response);
}
ajax('URL', callback);

Of (de bovenstaande is beter, anonieme functies zijn altijd een probleem):

ajax('URL', function(e){console.log(this.response)});

Niets gemakkelijker.

Sommige mensen zullen waarschijnlijk zeggen dat het beter is om onreadystatechange of zelfs de XMLHttpRequest-variabelenaam te gebruiken. Dat is verkeerd.

Uitchecken XMLHttpVerzoek geavanceerde functies

Het wordt ondersteund op alle * moderne browsers. En ik kan bevestigen als ik deze aanpak gebruik sinds XMLHttpRequest 2 bestaat. Ik heb nooit problemen gehad met alle browsers die ik gebruik.

onreadystatechange is alleen nuttig als u de headers op status 2 wilt krijgen.

De ... gebruiken XMLHttpRequest variabele naam is een andere grote fout omdat je de callback binnen de onload / oreadystatechange sluitingen moet uitvoeren anders heb je hem verloren.


Als u nu wat complexer wilt worden met post en FormData, kunt u deze functie eenvoudig uitbreiden:

function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
  c = new XMLHttpRequest;
  c.open(e||'get', a);
  c.onload = b;
  c.send(d||null)
}

Nogmaals ... het is een zeer korte functie, maar het krijgt & plaatst.

Voorbeelden van gebruik:

x(url, callback); // By default it's get so no need to set
x(url, callback, 'post', {'key': 'val'}); // No need to set post data

Of geef een volledig formulierelement door (document.getElementsByTagName('form')[0]):

var fd = new FormData(form);
x(url, callback, 'post', fd);

Of stel een aantal aangepaste waarden in:

var fd = new FormData();
fd.append('key', 'val')
x(url, callback, 'post', fd);

Zoals je kunt zien, heb ik geen synchronisatie geïmplementeerd ... het is een slechte zaak.

Dat gezegd hebbende ... waarom doe je het niet op de gemakkelijke manier?


Zoals vermeld in de opmerking, maakt het gebruik van error && synchrone het punt van het antwoord volledig uit. Wat is een leuke korte manier om Ajax op de juiste manier te gebruiken?

Fout handler

function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
  c = new XMLHttpRequest;
  c.open(e||'get', a);
  c.onload = b;
  c.onerror = error;
  c.send(d||null)
}

function error(e){
  console.log('--Error--', this.type);
  console.log('this: ', this);
  console.log('Event: ', e)
}
function displayAjax(e){
  console.log(e, this);
}
x('WRONGURL', displayAjax);

In het bovenstaande script hebt u een foutafhandelingsprogramma dat statisch is gedefinieerd, zodat het de functie niet schaadt. De foutenbehandelaar kan ook voor andere functies worden gebruikt.

Maar om echt een foutmelding te krijgen, is de enkel en alleen manier is om een ​​verkeerde URL te schrijven, in welk geval elke browser een fout genereert.

Fouthandlers zijn misschien handig als u aangepaste headers instelt, het responseType instelt op blob array-buffer of wat dan ook ....

Zelfs als u 'POSTAPAPAP' als de methode doorgeeft, zal het geen fout veroorzaken.

Zelfs als u 'fdggdgilfdghfldj' als formdata doorgeeft, zal het geen fout veroorzaken.

In het eerste geval bevindt de fout zich in de displayAjax() onder this.statusText als Method not Allowed.

In het tweede geval werkt het gewoon. Je moet bij de server controleren of je de juiste berichtgegevens hebt doorgegeven.

cross-domein niet toegestaan ​​gooit automatisch fout.

In de foutreactie zijn er geen foutcodes.

Er is alleen de this.type die op fout is ingesteld.

Waarom zou u een fout-afhandelingsprogramma toevoegen als u totaal geen controle over fouten hebt? De meeste fouten worden hierbinnen geretourneerd in de callback-functie displayAjax().

Dus: geen behoefte aan foutcontroles als u de URL correct kunt kopiëren en plakken. ;)

PS: Als de eerste test schreef ik x ('x', displayAjax) ... en kreeg het totaal een reactie ... ??? Dus ik controleerde de map waar de HTML zich bevond, en er was een bestand met de naam 'x.xml'. Dus zelfs als u de extensie van uw bestand vergeet XMLHttpRequest 2 WILL FIND IT. Ik LOL'd


Lees een synchroon bestand

Doe dat niet.

Als je de browser een tijdje wilt blokkeren, laad dan een mooi groot txt-bestand synchroon.

function omg(a, c){ // URL
  c = new XMLHttpRequest;
  c.open('GET', a, true);
  c.send();
  return c; // Or c.response
}

Nu kan je het doen

 var res = omg('thisIsGonnaBlockThePage.txt');

Er is geen andere manier om dit op een niet-asynchrone manier te doen. (Ja, met lus setTimeout ... maar serieus?)

Een ander punt is ... als je met API's werkt of alleen de bestanden van je lijst hebt, of wat je altijd verschillende functies voor elk verzoek gebruikt ...

Alleen als u een pagina hebt waar u altijd dezelfde XML / JSON laadt of wat u maar één functie nodig hebt. Pas in dat geval de Ajax-functie iets aan en vervang b met uw speciale functie.


De bovenstaande functies zijn voor basisgebruik.

Als u de functie EXTEND wilt VERLENGEN ...

Ja, dat kan.

Ik gebruik veel API's en een van de eerste functies die ik in elke HTML-pagina integreer, is de eerste Ajax-functie in dit antwoord, met alleen GET ...

Maar je kunt veel dingen doen met XMLHttpRequest 2:

Ik heb een downloadmanager gemaakt (gebruikmakend van ranges aan beide kanten met cv, filereader, bestandssysteem), verschillende image resizers converters die canvas gebruiken, websql-databases vullen met base64 images en nog veel meer ... Maar in deze gevallen zou je een functie alleen voor dat doel moeten creëren ... soms heb je een blob nodig, arraybuffers, kun je headers instellen, mimetype overschrijven en er is nog veel meer ...

Maar de vraag is hier hoe je een reactie van Ajax kunt retourneren ... (Ik voegde een eenvoudige manier toe.)


302
2017-08-19 08:06



Als je beloftes gebruikt, is dit antwoord voor jou.

Dit betekent AngularJS, jQuery (met uitgesteld), native XHR's vervanging (fetch), EmberJS, BackboneJS's save of een knooppuntbibliotheek die beloftes oplevert.

Uw code zou iets in de trant van dit moeten zijn:

function foo() {
    var data;
    // or $.get(...).then, or request(...).then, or query(...).then
    fetch("/echo/json").then(function(response){
        data = response.json();
    });
    return data;
}

var result = foo(); // result is always undefined no matter what.

Felix Kling heeft goed werk geleverd door een antwoord te schrijven voor mensen die jQuery gebruiken met callbacks voor AJAX. Ik heb een antwoord voor native XHR. Dit antwoord is voor generiek gebruik van beloften op de frontend of backend.


Het kernprobleem

Het JavaScript-concurrency-model in de browser en op de server met NodeJS / io.js is asynchrone en reagerend.

Wanneer je een methode noemt die een belofte teruggeeft, de then handlers zijn altijd asynchroon uitgevoerd - dat wil zeggen, na de code onder hen die niet in een is .then handler.

Dit betekent wanneer u terugkeert data de then handler die u hebt gedefinieerd, nog niet heeft uitgevoerd. Dit betekent op zijn beurt dat de waarde die u terugkeert niet op tijd in de juiste waarde is ingesteld.

Hier is een eenvoudige analogie voor het probleem:

    function getFive(){
        var data;
        setTimeout(function(){ // set a timer for one second in the future
           data = 5; // after a second, do this
        }, 1000);
        return data;
    }
    document.body.innerHTML = getFive(); // `undefined` here and not 5

De waarde van data is undefined sinds de data = 5 deel is nog niet uitgevoerd. Het zal waarschijnlijk binnen een seconde worden uitgevoerd, maar op dat moment is het niet relevant voor de geretourneerde waarde.

Omdat de bewerking nog niet is gebeurd (AJAX, serveroproep, IO, timer), geeft u de waarde terug voordat het verzoek de kans heeft gekregen om uw code te vertellen wat die waarde is.

Een mogelijke oplossing voor dit probleem is coderen re-actief , vertel je programma wat je moet doen als de berekening is voltooid. Beloften maken dit actief mogelijk door tijdelijk (tijdgevoelig) van aard te zijn.

Beknopte samenvatting van beloften

Een belofte is een waarde in de tijd. Beloften hebben staat, ze beginnen als hangend zonder waarde en kunnen afrekenen met:

  • vervuld wat betekent dat de berekening met succes is voltooid.
  • verworpen wat betekent dat de berekening is mislukt.

Een belofte kan alleen staten veranderen een keer waarna het altijd voor altijd in dezelfde staat zal blijven. Je kunt hechten then handlers toe belooft om hun waarde te extraheren en fouten af ​​te handelen. then handlers toestaan chaining van oproepen. Beloften worden gecreëerd door met behulp van API's die deze retourneren. Bijvoorbeeld de modernere AJAX-vervanging fetch of jQuery's $.get beloofde beloftes.

Wanneer we bellen .then op een belofte en terugkeer iets ervan - we krijgen een belofte voor de verwerkte waarde. Als we nog een belofte teruggeven, zullen we verbazingwekkende dingen krijgen, maar laten we onze paarden vasthouden.

Met beloften

Laten we eens kijken hoe we het bovenstaande probleem kunnen oplossen met beloften. Laten we eerst ons begrip van beloftestaten van bovenaf tonen door de Bouwer beloven voor het maken van een vertragingsfunctie:

function delay(ms){ // takes amount of milliseconds
    // returns a new promise
    return new Promise(function(resolve, reject){
        setTimeout(function(){ // when the time is up
            resolve(); // change the promise to the fulfilled state
        }, ms);
    });
}

Nu we setTimeout geconverteerd hebben om beloften te gebruiken, kunnen we gebruiken then om het te laten tellen:

function delay(ms){ // takes amount of milliseconds
  // returns a new promise
  return new Promise(function(resolve, reject){
    setTimeout(function(){ // when the time is up
      resolve(); // change the promise to the fulfilled state
    }, ms);
  });
}

function getFive(){
  // we're RETURNING the promise, remember, a promise is a wrapper over our value
  return delay(100).then(function(){ // when the promise is ready
      return 5; // return the value 5, promises are all about return values
  })
}
// we _have_ to wrap it like this in the call site, we can't access the plain value
getFive().then(function(five){ 
   document.body.innerHTML = five;
});

Kortom, in plaats van het terugsturen van een waarde wat we niet kunnen doen vanwege het concurrency-model - we komen terug met een wikkel voor een waarde die we kunnen openmaken met then. Het is net een doos waarmee je kunt openen then.

Dit toepassen

Dit staat hetzelfde voor uw oorspronkelijke API-oproep, u kunt:

function foo() {
    // RETURN the promise
    return fetch("/echo/json").then(function(response){
        return response.json(); // process it inside the `then`
    });
}

foo().then(function(response){
    // access the value inside the `then`
})

Dus dit werkt net zo goed. We hebben geleerd dat we geen waarden kunnen retourneren van al asynchrone oproepen, maar we kunnen beloftes gebruiken en deze ketenen om verwerking uit te voeren. We weten nu hoe we het antwoord van een asynchrone oproep kunnen retourneren.

ES2015 (ES6)

ES6 introduceert generatoren Dit zijn functies die in het midden kunnen terugkeren en vervolgens het punt hervatten waar ze zich bevonden. Dit is meestal handig voor sequenties, bijvoorbeeld:

function* foo(){ // notice the star, this is ES6 so new browsers/node/io only
    yield 1;
    yield 2;
    while(true) yield 3;
}

Is een functie die een retourneert iterator over de reeks 1,2,3,3,3,3,.... wat geïtereerd kan worden. Hoewel dit op zichzelf interessant is en ruimte biedt voor veel mogelijkheden, is er één interessant geval.

Als de reeks die we produceren een reeks handelingen is in plaats van cijfers, kunnen we de functie pauzeren wanneer een actie wordt uitgevoerd en wachten voordat we de functie hervatten. Dus in plaats van een reeks getallen hebben we een reeks nodig toekomst waarden - dat wil zeggen: beloften.

Deze enigszins lastige maar zeer krachtige truc laat ons asynchrone code synchroon schrijven. Er zijn verschillende 'hardlopers' die dit voor je doen, het schrijven ervan is een korte paar regels code, maar valt buiten het bestek van dit antwoord. Ik gebruik Bluebird's Promise.coroutine hier, maar er zijn andere wrappers zoals co of Q.async.

var foo = coroutine(function*(){
    var data = yield fetch("/echo/json"); // notice the yield
    // code here only executes _after_ the request is done
    return data.json(); // data is defined
});

Deze methode retourneert een belofte zelf, die we kunnen gebruiken van andere coroutines. Bijvoorbeeld:

var main = coroutine(function*(){
   var bar = yield foo(); // wait our earlier coroutine, it returns a promise
   // server call done here, code below executes when done
   var baz = yield fetch("/api/users/"+bar.userid); // depends on foo's result
   console.log(baz); // runs after both requests done
});
main();

ES2016 (ES7)

In ES7 is dit verder gestandaardiseerd, er zijn nu verschillende voorstellen, maar in alle gevallen kunt u dit await belofte. Dit is slechts "suiker" (leukere syntaxis) voor het ES6-voorstel hierboven door het toevoegen van de async en await zoekwoorden. Het bovenstaande voorbeeld maken:

async function foo(){
    var data = await fetch("/echo/json"); // notice the await
    // code here only executes _after_ the request is done
    return data.json(); // data is defined
}

Het geeft nog steeds een belofte terug, hetzelfde :)


243
2018-05-12 02:22



Je gebruikt Ajax verkeerd. Het idee is niet om iets terug te krijgen, maar in plaats daarvan de gegevens over te dragen aan iets dat een callback-functie wordt genoemd en die de gegevens verwerkt.

Dat is:

function handleData( responseData ) {

    // Do what you want with the data
    console.log(responseData);
}

$.ajax({
    url: "hi.php",
    ...
    success: function ( data, status, XHR ) {
        handleData(data);
    }
});

Het retourneren van iets in de verzendhandler doet niets. U moet in plaats hiervan de gegevens overdragen of doen wat u wilt, direct in de succesfunctie.


192
2018-05-23 02:05



De eenvoudigste oplossing is om een ​​JavaScript-functie te maken en deze voor het Ajax te noemen success Bel terug.

function callServerAsync(){
    $.ajax({
        url: '...',
        success: function(response) {

            successCallback(response);
        }
    });
}

function successCallback(responseObj){
    // Do something like read the response and show data
    alert(JSON.stringify(responseObj)); // Only applicable to JSON response
}

function foo(callback) {

    $.ajax({
        url: '...',
        success: function(response) {
           return callback(null, response);
        }
    });
}

var result = foo(function(err, result){
          if (!err)
           console.log(result);    
}); 

184
2018-02-18 18:58



Ik zal antwoorden met een vreselijk uitziende, met de hand getekende strip. De tweede afbeelding is de reden waarom result is undefined in uw codevoorbeeld.

enter image description here


154
2017-08-11 14:17



Angular1

Voor mensen die gebruiken angularjs, kan deze situatie gebruiken met Promises.

Hier het zegt,

Beloften kunnen worden gebruikt om onnauwkeurige asynchrone functies te gebruiken en om meerdere functies samen te ketenen.

Je kunt een leuke uitleg vinden hier ook.

Voorbeeld gevonden in docs hieronder vermeld.

  promiseB = promiseA.then(
    function onSuccess(result) {
      return result + 1;
    }
    ,function onError(err) {
      //Handle error
    }
  );

 // promiseB will be resolved immediately after promiseA is resolved 
 // and its value will be the result of promiseA incremented by 1.

Angular2 en later

In Angular2 met bekijk het volgende voorbeeld, maar het is aanbevolen gebruiken Observables met Angular2.

 search(term: string) {
     return this.http
  .get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
  .map((response) => response.json())
  .toPromise();

}

Je kunt dat op deze manier consumeren,

search() {
    this.searchService.search(this.searchField.value)
      .then((result) => {
    this.result = result.artists.items;
  })
  .catch((error) => console.error(error));
}

Zie de origineel post hier. Maar Typescript ondersteunt het niet native es6 Beloften, als je het wilt gebruiken, heb je daar mogelijk een plug-in voor nodig.

Daarnaast zijn hier de beloften spec definieer hier.


113
2017-08-26 08:11



De meeste antwoorden geven hier nuttige suggesties voor wanneer u een enkele asynchrone bewerking uitvoert, maar soms komt dit naar voren wanneer u een asynchrone bewerking moet uitvoeren voor elk invoer in een array of een andere lijstachtige structuur. De verleiding is om dit te doen:

// WRONG
var results = [];
theArray.forEach(function(entry) {
    doSomethingAsync(entry, function(result) {
        results.push(result);
    });
});
console.log(results); // E.g., using them, returning them, etc.

Voorbeeld:

// WRONG
var theArray = [1, 2, 3];
var results = [];
theArray.forEach(function(entry) {
    doSomethingAsync(entry, function(result) {
        results.push(result);
    });
});
console.log("Results:", results); // E.g., using them, returning them, etc.

function doSomethingAsync(value, callback) {
    console.log("Starting async operation for " + value);
    setTimeout(function() {
        console.log("Completing async operation for " + value);
        callback(value * 2);
    }, Math.floor(Math.random() * 200));
}
.as-console-wrapper {
  max-height: 100% !important;
}

De reden dat niet werkt, is dat de callbacks van doSomethingAsync nog niet zijn gestart op het moment dat u de resultaten probeert te gebruiken.

Dus als u een array (of een lijst van een soort) hebt en asynchrone bewerkingen wilt uitvoeren voor elk item, hebt u twee opties: Voer de bewerkingen parallel (overlappend) of in serie (opeenvolgend achtereenvolgens) uit.

Parallel

U kunt ze allemaal starten en bijhouden hoeveel callbacks u verwacht en vervolgens de resultaten gebruiken wanneer u zoveel callbacks hebt gekregen:

var results = [];
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
    doSomethingAsync(entry, function(result) {
        results[index] = result;
        if (--expecting === 0) {
            // Done!
            console.log("Results:", results); // E.g., using the results
        }
    });
});

Voorbeeld:

var theArray = [1, 2, 3];
var results = [];
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
    doSomethingAsync(entry, function(result) {
        results[index] = result;
        if (--expecting === 0) {
            // Done!
            console.log("Results:", results); // E.g., using the results
        }
    });
});

function doSomethingAsync(value, callback) {
    console.log("Starting async operation for " + value);
    setTimeout(function() {
        console.log("Completing async operation for " + value);
        callback(value * 2);
    }, Math.floor(Math.random() * 200));
}
.as-console-wrapper {
  max-height: 100% !important;
}

(We zouden kunnen afschaffen expecting en gebruik gewoon results.length === theArray.length, maar dat laat ons open voor de mogelijkheid dat theArray wordt gewijzigd terwijl de oproepen openstaan ​​...)

Merk op hoe we het gebruiken index van forEach om het resultaat op te slaan results in dezelfde positie als het item waar het betrekking op heeft, zelfs als de resultaten buiten de order vallen (aangezien asynchrone oproepen niet noodzakelijkerwijs compleet zijn in de volgorde waarin ze zijn gestart).

Maar wat als je moet terugkeer die resultaten van een functie? Zoals de andere antwoorden hebben opgemerkt, kunt u niet; je moet je functie laten accepteren en een callback bellen (of terugsturen Belofte). Hier is een callback-versie:

function doSomethingWith(theArray, callback) {
    var results = [];
    var expecting = theArray.length;
    theArray.forEach(function(entry, index) {
        doSomethingAsync(entry, function(result) {
            results[index] = result;
            if (--expecting === 0) {
                // Done!
                callback(results);
            }
        });
    });
}
doSomethingWith(theArray, function(results) {
    console.log("Results:", results);
});

Voorbeeld:

function doSomethingWith(theArray, callback) {
    var results = [];
    var expecting = theArray.length;
    theArray.forEach(function(entry, index) {
        doSomethingAsync(entry, function(result) {
            results[index] = result;
            if (--expecting === 0) {
                // Done!
                callback(results);
            }
        });
    });
}
doSomethingWith([1, 2, 3], function(results) {
    console.log("Results:", results);
});

function doSomethingAsync(value, callback) {
    console.log("Starting async operation for " + value);
    setTimeout(function() {
        console.log("Completing async operation for " + value);
        callback(value * 2);
    }, Math.floor(Math.random() * 200));
}
.as-console-wrapper {
  max-height: 100% !important;
}

Of hier is een versie die een retourneert Promise in plaats daarvan:

function doSomethingWith(theArray) {
    return new Promise(function(resolve) {
        var results = [];
        var expecting = theArray.length;
        theArray.forEach(function(entry, index) {
            doSomethingAsync(entry, function(result) {
                results[index] = result;
                if (--expecting === 0) {
                    // Done!
                    resolve(results);
                }
            });
        });
    });
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

Natuurlijk als doSomethingAsync gaf ons fouten, we zouden gebruiken reject om de belofte te verwerpen toen we een fout kregen.)

Voorbeeld:

function doSomethingWith(theArray) {
    return new Promise(function(resolve) {
        var results = [];
        var expecting = theArray.length;
        theArray.forEach(function(entry, index) {
            doSomethingAsync(entry, function(result) {
                results[index] = result;
                if (--expecting === 0) {
                    // Done!
                    resolve(results);
                }
            });
        });
    });
}
doSomethingWith([1, 2, 3]).then(function(results) {
    console.log("Results:", results);
});

function doSomethingAsync(value, callback) {
    console.log("Starting async operation for " + value);
    setTimeout(function() {
        console.log("Completing async operation for " + value);
        callback(value * 2);
    }, Math.floor(Math.random() * 200));
}
.as-console-wrapper {
  max-height: 100% !important;
}

(Of je zou er een wrapper voor kunnen maken doSomethingAsync dat geeft een belofte terug, en doe dan de onderstaande ...)

Als doSomethingAsync geeft je een Belofte, je kunt gebruiken Promise.all:

function doSomethingWith(theArray) {
    return Promise.all(theArray.map(function(entry) {
        return doSomethingAsync(entry, function(result) {
            results.push(result);
        });
    }));
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

Voorbeeld:

function doSomethingWith(theArray) {
    return Promise.all(theArray.map(function(entry) {
        return doSomethingAsync(entry, function(result) {
            results.push(result);
        });
    }));
}
doSomethingWith([1, 2, 3]).then(function(results) {
    console.log("Results:", results);
});

function doSomethingAsync(value) {
    console.log("Starting async operation for " + value);
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log("Completing async operation for " + value);
            resolve(value * 2);
        }, Math.floor(Math.random() * 200));
    });
}
.as-console-wrapper {
  max-height: 100% !important;
}

Let daar op Promise.all lost zijn belofte op met een hele reeks resultaten van alle beloften die u hem geeft als ze allemaal zijn opgelost, of verwerpt de belofte als de eerste van de beloften die je doet, verwerpt het.

Serie

Stel dat je niet wilt dat de operaties parallel lopen? Als u ze één voor één wilt uitvoeren, moet u wachten tot elke bewerking is voltooid voordat u met de volgende begint. Hier is een voorbeeld van een functie die dat doet en een callback roept met het resultaat:

function doSomethingWith(theArray, callback) {
    var results = [];
    doOne(0);
    function doOne(index) {
        if (index < theArray.length) {
            doSomethingAsync(theArray[index], function(result) {
                results.push(result);
                doOne(index + 1);
            });
        } else {
            // Done!
            callback(results);
        }
    }
}
doSomethingWith(theArray, function(results) {
    console.log("Results:", results);
});

(Aangezien we het werk in serie doen, kunnen we het gewoon gebruiken results.push(result) omdat we weten dat we de resultaten niet in orde zullen krijgen. In het bovenstaande hadden we kunnen gebruiken results[index] = result;, maar in sommige van de volgende voorbeelden hebben we geen index om te gebruiken.)

Voorbeeld:

function doSomethingWith(theArray, callback) {
    var results = [];
    doOne(0);
    function doOne(index) {
        if (index < theArray.length) {
            doSomethingAsync(theArray[index], function(result) {
                results.push(result);
                doOne(index + 1);
            });
        } else {
            // Done!
            callback(results);
        }
    }
}
doSomethingWith([1, 2, 3], function(results) {
    console.log("Results:", results);
});

function doSomethingAsync(value, callback) {
    console.log("Starting async operation for " + value);
    setTimeout(function() {
        console.log("Completing async operation for " + value);
        callback(value * 2);
    }, Math.floor(Math.random() * 200));
}
.as-console-wrapper {
  max-height: 100% !important;
}

(Of, wederom, bouw een wrapper voor doSomethingAsync dat geeft je een belofte en doe de onderstaande ...)

Als doSomethingAsync geeft je een belofte, als je ES2017 + syntaxis kunt gebruiken (misschien met een transpilervorm zoals Babel), kunt u een async functie met for-of en await:

async function doSomethingWith(theArray) {
    const results = [];
    for (const entry of theArray) {
        results.push(await doSomethingAsync(entry));
    }
    return results;
}
doSomethingWith(theArray).then(results => {
    console.log("Results:", results);
});

Voorbeeld:

async function doSomethingWith(theArray) {
    const results = [];
    for (const entry of theArray) {
        results.push(await doSomethingAsync(entry));
    }
    return results;
}
doSomethingWith([1, 2, 3]).then(function(results) {
    console.log("Results:", results);
});

function doSomethingAsync(value) {
    console.log("Starting async operation for " + value);
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log("Completing async operation for " + value);
            resolve(value * 2);
        }, Math.floor(Math.random() * 200));
    });
}
.as-console-wrapper {
  max-height: 100% !important;
}

Als u de ES2017 + -syntaxis (nog) niet kunt gebruiken, kunt u een variatie op de "Promise reduce" -patroon (dit is complexer dan de gebruikelijke belofte verminderen omdat we het resultaat niet van het ene naar het volgende resultaat doorgeven, maar in plaats daarvan de resultaten verzamelen in een array):

function doSomethingWith(theArray) {
    return theArray.reduce(function(p, entry) {
        return p.then(function(results) {
            return doSomethingAsync(entry).then(function(result) {
                results.push(result);
                return results;
            });
        });
    }, Promise.resolve([]));
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

Voorbeeld:

function doSomethingWith(theArray) {
    return theArray.reduce(function(p, entry) {
        return p.then(function(results) {
            return doSomethingAsync(entry).then(function(result) {
                results.push(result);
                return results;
            });
        });
    }, Promise.resolve([]));
}
doSomethingWith([1, 2, 3]).then(function(results) {
    console.log("Results:", results);
});

function doSomethingAsync(value) {
    console.log("Starting async operation for " + value);
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log("Completing async operation for " + value);
            resolve(value * 2);
        }, Math.floor(Math.random() * 200));
    });
}
.as-console-wrapper {
  max-height: 100% !important;
}

... wat minder omslachtig is ES2015 + pijlfuncties:

function doSomethingWith(theArray) {
    return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
        results.push(result);
        return results;
    })), Promise.resolve([]));
}
doSomethingWith(theArray).then(results => {
    console.log("Results:", results);
});

Voorbeeld:

function doSomethingWith(theArray) {
    return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
        results.push(result);
        return results;
    })), Promise.resolve([]));
}
doSomethingWith([1, 2, 3]).then(function(results) {
    console.log("Results:", results);
});

function doSomethingAsync(value) {
    console.log("Starting async operation for " + value);
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log("Completing async operation for " + value);
            resolve(value * 2);
        }, Math.floor(Math.random() * 200));
    });
}
.as-console-wrapper {
  max-height: 100% !important;
}


90
2018-05-03 16:59



Bekijk dit voorbeeld:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope,$http) {

    var getJoke = function(){
        return $http.get('http://api.icndb.com/jokes/random').then(function(res){
            return res.data.value;  
        });
    }

    getJoke().then(function(res) {
        console.log(res.joke);
    });
});

Zoals je kan zien getJoke is terugsturen opgelost belofte (het is opgelost bij terugkomst res.data.value). Dus je wacht tot het $ http.get aanvraag is voltooid en vervolgens console.log (res.joke) wordt uitgevoerd (als een normale asynchrone stroom).

Dit is de plnkr:

http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/


73
2018-06-02 08:31



Een andere manier om een ​​waarde terug te halen uit een asynchrone functie is om een ​​object door te geven dat het resultaat van de asynchrone functie zal opslaan.

Hier is een voorbeeld van hetzelfde:

var async = require("async");

// This wires up result back to the caller
var result = {};
var asyncTasks = [];
asyncTasks.push(function(_callback){
    // some asynchronous operation
    $.ajax({
        url: '...',
        success: function(response) {
            result.response = response;
            _callback();
        }
    });
});

async.parallel(asyncTasks, function(){
    // result is available after performing asynchronous operation
    console.log(result)
    console.log('Done');
});

Ik gebruik de result object om de waarde op te slaan tijdens de asynchrone bewerking. Hierdoor is het resultaat beschikbaar, zelfs na de asynchrone taak.

Ik gebruik deze aanpak veel. Ik zou graag willen weten hoe goed deze aanpak werkt, waar het bekabelen van het resultaat door achtereenvolgende modules een rol speelt.


69
2017-09-02 12:54