Zruck zum Blog, du Zniachtl
Mai 2018·4 Min. zum LesnVo da KI übersetzt

Javascript Promises

#development#javascript#programmierung#promise

Seit Juni 2015 sand Promises mit ES6 a in Javascript ankemman und kinnan do nativ gnutzt wern. Vielleicht geht's einigen do so wia ma am Anfang und sie wissn ned so recht, wofür Promises sinnvoll sand oda wia ma sie nutzt.

Wos sand Promises?

Javascript is "Singlethreaded" und orbeit daher sequenziell bzw. synchron. Promises führn jetzt kurz gsogt mehrere Funktionen nacheinander aus, genauer: Mia kinnan Funktion 2 genau dann aufrufn, wenn Funktion 1 abgschlossn wurde. Mia kinnan also zuerst a Handlung ausführn, und erst wenn de abgschlossn is, de nächste Handlung starten. Sinnvoll is des Ganze zum Beispiel bei am Ajax-Request: Wenn mia die Valorbeitung vo de Daten erst dann starten wolln, sobois da Ajax-Request abgschlossn is, kinnan mia dafür a Promise nutzn, wobei zusätzlich danoch unterschieden wird, ob da Promise Erfolg ghobt hot oda an Fehler hervorgrufn hot. Ohne Promise tät Javascript scho weitermochn, a wenn da Ajax-Request no ned abgschlossn is, mit dem Resultat, dass da Rückgabewert unter Umständen no leer is. Sinnvoll sand Promises daher nur bei asynchronen Aktivitäten - bei synchronen kinnan mia uns auf die sequenzielle Valorbeitung vo Javascript valossn. Synchroner Code is sehr einfach - er wird von oben noch unten ausgführt und Schritt 2 wartet imma erst, bis Schritt 1 abgschlossn is. Mia miassn also imma wartn, bis a Aktion abgschlossn is, um a folgende Aktion auszuführn, wos nervig is und vor oim Zeit braucht, de am End dazu führt, dass des Skript umso länger braucht, bis's fertig is. Schlimmer no - wenn mia den Javascript-Code ned am End vo da Seitn platziern, führt des dazu, dass die Ausführung vom Javascript in Konkurrenz zum Rendern vo da Seitn steht (Javascript, CSS, HTML etc. teilt si den söbn Thread - die Ausführung von am Javascript blockiert also den weiteren Aufbau vo da Webseitn) und somit da Seitnaufbau nur langsam vorankummt. Des ärgert den Endnutzer, und verärgerte Endnutzer verärgern den Entwickler.

Zustände

Da Promise kann 4 Zustände hobn:

  • Pending: Da Promise is no in Teil 1 - woar also bisher weder erfolgreich noch gscheitert
  • Fulfilled: Operation abgschlossn -> Fulfilled-Funktion starten
  • Rejected: Es is a Fehler aufgetreten -> Rejected-Funktion ausführn
  • Settled: Promise is abgschlossn und entweder rejected oda fulfilled

Warum ned if und if und if und if...?

Mia kinnan natürlich a den Code in a Menge, Menge IF-Abfragen verschachteln und kriagn dann die berüchtigte Pyramid of doom. Mit Promises kinnan mia des vameidn.

Syntax

De Syntax von am Promise schaut so aus new Promise(function(resolve, reject) { / CODE / });. Im Code kinnan jetzt die Funktionen / Argumente resolve() (führt zum Status "fulfilled" und wird aufgrufn, wenn da Code koan Fehler zruckgibt / da Promise erfolgreich woar) und reject() (führt zum Status "rejected" und wird aufgrufn, wenn da Code an Fehler aufweist / da Promise ned erfolgreich woar) aufgrufn wern.

Basics

A kurzes Beispiel wär entsprechend:

var promise = new Promise(function(resolve, reject) {
  // Hier deinen Code einsetzen, der bei Erfolg success = true setzt
  success === true ? resolve('Gut') : reject('Schlecht');
});
promise.then(function(result) {
  console.log("Erfolg:");
  console.log(result);
}, function(result) {
  console.log("Fehler:");
  console.log(result);
});

Solang dein Code ausgführt wird, is da Promise im Status "Pending", sobois er abgschlossn is, im Status "Settled", und zwoar entweder Fulfilled (wenn success === true) und resolve() wird aufgrufn, oda Rejected (wenn success === false) und reject() wird aufgrufn. Da Promise-Konstruktor kriagt also an Callback mit zwoa Parametern übergebn: Resolve (Handlung erfolgreich abgschlossn) und Reject (Fehler is aufgetreten). Sobois da Code abgschlossn is (promise.then()), wird je nachdem, ob resolve() oda reject() aufgrufn wird, entweder "Erfolg: Gut" oda "Fehler: Schlecht" ausgebn. Auf "Deitsch": De Variable promise enthoit den Promise. Promise.then() kriagt ois Parameter die zwoa Funktionen, de mia in "new Promise" definiert hom - des entspricht dann also in etwa promise.then(function resolve(result){}, function reject(result){});. Da Vorteil liegt jetzt drin, dass resolve() und reject() eben erst dann aufgrufn wern, wenn da Code im Promise ausgführt wurde. Grod bei asynchronen Ajax-Requests is des sinnvoll - so kinnan mia die Daten aus dem Request erst dann valorbeitn, wenn da Request a abgschlossn wurde.

Asynchroner Beispielcode

Ois Grundlage für olle folgenden Beispiele nehmen mia diesen asynchronen AJAX-Request.

function GET(target) {
  return new Promise(function(success, error) {
    var request = new XMLHttpRequest();
    request.open("GET", target);
    request.addEventListener("load", function() {
      if (this.status == 200) {
        success('Erfolgreich!');
      } else {
        error(this.status);
      }
    }, false);
    request.send(target);
  });
}

Promising the promise

Um die Valwirrung perfekt zu machn, gebn resolve() und reject() ihrerseits wieda a Promise zruck, mia kinnan also mehrere Promises aneinanderhängn und vaketten.

GET("file1.html")
  .then(GET("file2.html"))
  .then(GET("file3.html"));

Mia lodn also erst file1.html, danach file2.html, danach file3.html. De "success"-Funktion mocht also nix ondres, ois wiederum a Promise zu erstöin, jedoch mit ana ondern Datei.

Promise: It will be an array

Ma muass ned mehrere identische Promises aneinanderhängn, um sie zu vaketten. Dafür gibt's die Methode all() - de nimmt mehrere Promise-Objekte ois Array o und führt olle Funktionen in dem Array ois Promise aus. Klans Beispiel:

Promise.all([GET("file1.html"), GET("file2.htlm")]).then(
  function (success) {
    console.log(success);
  },
  function (error) {
    console.log("Es trat ein Fehler auf:");
    console.log(error);
  }
);

Olle im Array enthoitenen Funktionen wern jetzt dem Promise übergebn. Sobois a Fehler auftritt, wird error() aufgrufn, und erst wenn olle Funktionen erfolgreich ausgführt worn sand, wird success() aufgrufn. Alternativ kinnan mia a catch nutzn: .catch(function(error) {}); Unser Beispiel säh dann so aus:

Promise.all([GET("file1.html"), GET("file2.htlm")]).then(
  function(success) {
    console.log(success);
  }).catch(
  function(error) {
    console.error(error);
  });

Schnellstes Promise

Promise.race() gibt nur a Promise zruck - und zwoar des, wos als erstes abgschlossn wurde.

Promise.race([GET("smallfile.jpg"), GET("bigfile.jpg"), GET("extrasmallfile.jpg")]).then(
  function (success) {
    console.log(success);
  }
);

Angnommen, smallfile hot a Größe von 200 MB, extrasmallfile hot a Größe von 2 KB, und bigfile a Größe von 3 GB. In dem Foi wird success() aufgrufn, und zwoar nachdem die Datei extrasmallfile aufgrufn wurde. Dadurch dass olle 3 Funktionsaufrufe asynchron ablaufn, muass a ned bigfile auf smallfile oda extrasmallfile auf bigfile wartn.

NeicherSPAM-Protection-Methoden Nr. 1: HoneypotElterSPAM vameidn mit qmail