Mehrere gleichzeitige Ajax-Anfragen (mit einem Callback) in jQuery

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Nehmen wir an, es gibt eine Funktion auf Ihrer Website, die nur zu 5 % der Zeit verwendet wird. Diese Funktion benötigt etwas HTML, CSS und JavaScript, um zu funktionieren. Sie entscheiden sich also, anstatt dieses HTML, CSS und JavaScript direkt auf der Seite zu haben, es per Ajax einzuladen, wenn die Funktion bald verwendet wird.

Wir müssen drei Ajax-Anfragen stellen. Da wir dem Benutzer nichts anzeigen möchten, bis die Funktion einsatzbereit ist (und sie sich alle gegenseitig bedingen, damit sie richtig funktionieren), müssen wir warten, bis alle drei abgeschlossen sind, bevor wir fortfahren.

Was ist der beste Weg, das zu tun?

Ajax-Aufrufe in jQuery bieten Callbacks

$.ajax({
  statusCode: {
    url: "/feature",
    success: function() {
      // Ajax success
    }
  }
});

Oder auf die "Deferred"-Art, diesmal mit der Kurzform der $.get()-Methode

$.get("/feature/").done(function() {
  // Ajax success
});

Aber wir müssen drei Ajax-Anfragen durchführen und wollen warten, bis alle drei abgeschlossen sind, bevor wir etwas tun. Das könnte im Callback-Dschungel ziemlich unübersichtlich werden.

// Get the HTML
$.get("/feature/", function(html) {

  // Get the CSS
  $.get("/assets/feature.css", function(css) {
    
    // Get the JavaScript
    $.getScript("/assets/feature.js", function() {

       // All is ready now, so...

       // Add CSS to page
       $("<style />").html(css).appendTo("head");

       // Add HTML to page
       $("body").append(html);

    });

  });

});

Dies wartet erfolgreich, bis alles bereit ist, bevor etwas zur Seite hinzugefügt wird. So ist bis zu dem Zeitpunkt, an dem der Benutzer etwas sieht, alles in Ordnung. Das mag für manche Übelkeit hervorrufen, aber ich habe so etwas schon früher gemacht. Zumindest ergibt es Sinn und funktioniert. Das Problem? Es ist langsam.

Eine Anfrage ... warten, bis sie fertig ist ... eine weitere Anfrage ... warten, bis sie fertig ist ... eine weitere Anfrage ... warten, bis sie fertig ist ... fertig.

Es wäre schneller, wenn wir könnten

Alle drei Anfragen parallel ... warten, bis alle drei fertig sind ... fertig.

Hier können wir etwas Deferred / Promises-Magie nutzen. Ich bin sicher, das ist für einige von Ihnen JavaScript 101, aber diese Art von Dingen ist mir lange entgangen und komplexere Promise-Sachen immer noch.

In unserem einfachen Anwendungsfall können wir die $.when()-Methode von jQuery verwenden, die eine Liste dieser "Deferred"-Objekte (Alle jQuery Ajax-Methoden geben Deferred-Objekte zurück) entgegennimmt und dann einen einzelnen Callback bereitstellt.

$.when(

  // Deferred object (probably Ajax request),

  // Deferred object (probably Ajax request),

  // Deferred object (probably Ajax request)

).then(function() {

  // All have been resolved (or rejected), do your thing

});

Unser Callback-Höllen kann also umgeschrieben werden wie

$.when(
  // Get the HTML
  $.get("/feature/", function(html) {
    globalStore.html = html;
  }),

  // Get the CSS
  $.get("/assets/feature.css", function(css) {
    globalStore.css = css;
  }),

  // Get the JS
  $.getScript("/assets/feature.js")

).then(function() {

  // All is ready now, so...

  // Add CSS to page
  $("<style />").html(globalStore.css).appendTo("head");

  // Add HTML to page
  $("body").append(globalStore.html);

});

Ein weiterer Anwendungsfall: Senf schneiden

Mein Anwendungsfallbeispiel ist eine 5%-Funktion. Halten Sie die Seite für die 95 % der Benutzer, die die Funktion nicht nutzen, leichter und machen Sie sie für diejenigen, die sie nutzen, zu einer relativ schnellen Ergänzung.

Eine andere Situation könnte eine "Senfschneide"-Situation sein, bei der Sie in bestimmten Situationen zusätzliche Funktionen oder Inhalte zu einer Seite hinzufügen, je nachdem, was Sie entscheiden. Vielleicht führen Sie einen matchMedia-Test mit einigen Media Queries durch und stellen fest, dass Bildschirmgröße und Fähigkeiten des Geräts so sind, dass Sie einige zusätzliche Module einbinden möchten. Toll, machen Sie das mit einigen parallelen Ajax-Aufrufen!