0% fanden dieses Dokument nützlich (0 Abstimmungen)
19 Ansichten76 Seiten

Web2 51 Javascript

Die Vorlesung behandelt fortgeschrittene Konzepte von JavaScript, einschließlich der Unterschiede zu Java, der Bedeutung von ECMAScript und der Einführung neuer Funktionen in ECMAScript 6 wie Arrow-Funktionen, Klassen und Objektliterale. Es werden grundlegende Aspekte wie Typsicherheit, Funktions-Pointer und die Verwendung von let und const erläutert, sowie die Bedeutung von Template-Strings und den Rest- und Spread-Operatoren. Die Vorlesung hebt hervor, dass JavaScript eine dynamische Sprache ist, die sich sowohl im Frontend als auch im Backend etabliert hat.

Hochgeladen von

Joey Pruessing
Copyright
© © All Rights Reserved
Wir nehmen die Rechte an Inhalten ernst. Wenn Sie vermuten, dass dies Ihr Inhalt ist, beanspruchen Sie ihn hier.
Verfügbare Formate
Als PDF, TXT herunterladen oder online auf Scribd lesen
0% fanden dieses Dokument nützlich (0 Abstimmungen)
19 Ansichten76 Seiten

Web2 51 Javascript

Die Vorlesung behandelt fortgeschrittene Konzepte von JavaScript, einschließlich der Unterschiede zu Java, der Bedeutung von ECMAScript und der Einführung neuer Funktionen in ECMAScript 6 wie Arrow-Funktionen, Klassen und Objektliterale. Es werden grundlegende Aspekte wie Typsicherheit, Funktions-Pointer und die Verwendung von let und const erläutert, sowie die Bedeutung von Template-Strings und den Rest- und Spread-Operatoren. Die Vorlesung hebt hervor, dass JavaScript eine dynamische Sprache ist, die sich sowohl im Frontend als auch im Backend etabliert hat.

Hochgeladen von

Joey Pruessing
Copyright
© © All Rights Reserved
Wir nehmen die Rechte an Inhalten ernst. Wenn Sie vermuten, dass dies Ihr Inhalt ist, beanspruchen Sie ihn hier.
Verfügbare Formate
Als PDF, TXT herunterladen oder online auf Scribd lesen
Sie sind auf Seite 1/ 76

JavaScript - Fortgeschritten

Web-Engineering II
Prof. Dr. Sebastian von Klinski
JavaScript
• Ist zu einer der wichtigsten Sprachen für Web-Development geworden
• Durch Node.js auch im Backend
• Java und JavaScript haben nur wenig gemein
• Der Umstieg von Java auf JavaScript ist häufig nicht leicht, weil die Syntax
zum Teil ähnlich ist, aber…
• In JavaScript die Typsicherheit fehlt
• In Java Konzepte wie Funktions-Pointer, Promises, Asynchrone
Funktionen und vieles mehr in dieser Form nicht existieren/ nicht gängig
sind
• Arrow-Funktionen eine vollkommen andere Syntax haben
• Etc.
• In dieser Vorlesung sollen einige wesentliche Unterschiede, bzw.
Besonderheiten von JavaScript erläutert werden

Beuth Hochschule für Technik Berlin – University of Applied Sciences 2


ECMAScript
• ECMAScript ist ein Standard
• ECMAScript ist Grundlage für diverse Sprachen: ActionScript, JavaScript,
JScript
• ECMAScript: Sub-Set von JavaScript
• Browser unterstützen in der Regel große Teile von ECMAScript, manche
jedoch nicht alles! (insbesondere IE und Edge)
• JavaScript…
• Früher Produkt von Sun, heute von Oracle
• Ist eine Implementierung von ECMAScript

Beuth Hochschule für Technik Berlin – University of Applied Sciences 3


JavaScript
• Zahlreiche Versionen von ECMAScript
• ECMAScript 3: Dezember 1999
• ECMAScript 4: Juli 2008
• ECMAScript 5: Dezember 2009
• ECMAScript 6: 2015
• ECMAScript 7: 2016
• ECMAScript 8: 2017
• ECMAScript 9: 2018
• Die meisten grundlegenden Neuerungen mit ECMAScript 6
• Hintergrund:
• Viele Web-Anwendungen sind heute clientseitige Web-Anwendungen
• Der Web-Client greift auf ein REST-Backend zu
• Veröffentlichung von clientseitigen Web-Bibliotheken wie React und
Angular

Beuth Hochschule für Technik Berlin – University of Applied Sciences 4


Neue Konzepte mit ECMAScript 6
• Einige Neuerungen sind recht einfach
• let, const, template strings
• Rest- und Spread-Operator
• Andere sind etwas komplexer, werden aber häufig genutzt
• Arrow-Funktionen
• Klassen
• Objektliterale
• Module
• Promise
• Weitere
• Generators, map/set/weakmap/weakset, Proxies, Symbols, Tail,
Reflection API, etc.

Beuth Hochschule für Technik Berlin – University of Applied Sciences 5


Grundlegende Aspekte

Beuth Hochschule für Technik Berlin – University of Applied Sciences 6


Funktions-Pointer
• In JavaScript kann mit Funktionen umgegangen werden wie mit Objekten
• Sie können
• Als Variablen definiert werden
• Als Parameter übergeben werden
• In Arrays abgelegt werden.
• Etc.

var func = function(a) {


return a + 1;
}

console.log("Value: " + func(2))

• Hinweis: in Funktionen müssen keine Datentypen angegeben werden!


• Seit Java 8 auch in Java über funktionale Interfaces möglich
Quelle: https://www.w3schools.com/js/js_es6.asp

7
Objekte
• In JavaScript sind Objekte keine Instanzen von Klassen, sondern
Sammlungen von Attributnamen und Werten, die im Initialisierer in
geschwungenen Klammern geschrieben werden

const object1 = { a: 'foo', b: 42, c: {} };

Quelle: https://www.w3schools.com/js/js_es6.asp

8
if
• If-Statements sind in JavaScript weniger strikt definiert als in Java
• Häufig wird if verwendet, um Objekte zu prüfen

var object = …

if(object) {

}

• Das if-Statement prüft, ob das Objekt „wahr“ ist…


• Es ist falsch, bei den folgenden Werten
• Null ▪ Leerer Text (z.B. „“)
• Undefined ▪ 0
• NaN ▪ false

9
Let
• Mit „let“ können Variablen deklariert werden, die nur in diesem Block sichtbar
sind

var x = 10;
// Here x is 10
{
let x = 2;
// Here x is 2
}
// Here x is 10

Quelle: https://www.w3schools.com/js/js_es6.asp

10
Const
• Mit „const“ können Konstanten deklariert werden, die nur in diesem Block
sichtbar sind

var x = 10;
// Here x is 10
{
const x = 2;
// Here x is 2
}
// Here x is 10

Quelle: https://www.w3schools.com/js/js_es6.asp

11
Template Strings
• Template-Strings sind String-Symbole, die über mehrere Zeilen gehende
Zeichenketten sowie eingebettete Javascript-Ausdrücke ermöglichen
• Werden über Accent-Grave eingeschlossen

var a = 5;
var b = 10;

console.log("Fifteen is " + (a + b) + " and\nnot " + (2 * a + b) + ".");

console.log(`Fifteen is ${a + b} and


not ${2 * a + b}.`);

Quelle: https://www.w3schools.com/js/js_es6.asp

12
Rest-Operator in Funktionen
• Beliebige Anzahl von Parametern können in Array geschrieben und
bearbeitet werden

function sum(...theArgs) {

console.log("Args: " + theArgs)

return theArgs.reduce((previous, current) => {


return previous + current;
});
}

console.log(sum(1, 2, 3));

Quelle: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions/rest_parameter

13
Spread-Operator
• Expandieren eines Ausdrucks (z.B. Arrays) an Stellen, wo mehrere
Parameter erwartet werden

function myFunction(v, w, x, y, z) { }
var args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);

var arr = [1,2,3];


var arr2 = [...arr];

var arr1 = [0, 1, 2];


var arr2 = [3, 4, 5];
arr1.push(...arr2);

Quelle: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/Spread_operator

14
Klassen

Beuth Hochschule für Technik Berlin – University of Applied Sciences 15


Klassen
• Die Definition von Klassen ist ähnlich wie in Java

class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}

print()
{
console.log("Rectangle: " + this.width + " / " + this.height)
}
}

var myRectangle = new Rectangle(3,2)


myRectangle.print()

Quelle: https://www.w3schools.com/js/js_es6.asp

16
Klassen
• Klassen müssen definiert werden, bevor davon Instanzen erzeugt werden
• Das ist bei Funktionen nicht notwendig!

var p = new Polygon(); // Fehler!

class Polygon {}

• Vererbung funktioniert ähnlich wie bei Java über „extends“

class Hund extends Tier{


sprich() {
console.log(this.name + ' bellt.');
}
}

Quelle: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Klassen

17
Klassen
• Es gibt mehrere Wege, Klassen zu definieren

// Anonyme Klassendeklarartion
var polygon = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};

// Klassendeklaration mit Namen


var polygon = class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
Quelle: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Klassen

18
Klassen
• Klassen werden über Funktionsprototypen umgesetzt und können auch
entsprechend dynamisch angelegt werde
• Klassen können auch von Funktionen erben!
function Tier() { }

Tier.prototype.sprich = function () {
console.log("Sprich")
return this;
}

let obj = new Tier();

obj.sprich()

let sprich = obj.sprich;


sprich(); // Globales Objekt

Quelle: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Klassen

19
Objektliterale

Beuth Hochschule für Technik Berlin – University of Applied Sciences 20


Objektliterale
• Ein bisschen wie „Klassen-light“, jedoch ohne Klassendeklaration
• Werden sehr häufig verwendet
• Es können Werte und Funktionen angelegt werden

var obj =
{
eigenschaft : 'blubb',
methode : function()
{
console.log(this.eigenschaft)
}
}

obj.methode()

Quelle: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Klassen

21
Objektliterale
• Werden sehr häufig für Rückgaben bei Funktionen und Services verwendet
• Direkte Überführung nach Json möglich

function getLaptop(make, model, year) {


return {
make: make,
model: model,
year: year
}
}

var laptop = getLaptop("Apple", "MacBook", "2015");


console.log("Maker: " + laptop.make)

Quelle: https://dev.to/sarah_chima/enhanced-object-literals-in-es6-a9d

22
Objektliterale
• Über den Spread-Operator (…) können Objektliterale zusammengeführt
werden
• Es wird ein neues Objekt erzeugt
• Gleiche Attribute werden überschrieben
• Hinweis: mit JSON.stringify() können Objekte auf Console ausgegeben werden

var obj1 = {
make: "Apple",
model: "Laptop",
year: 2020
}
var obj2 = {
name: "Udo",
make: "PC"
}
var obj3 = {...obj1, ...obj2}
console.log("Object 3: " + JSON.stringify(obj3))
Quelle: https://dev.to/sarah_chima/enhanced-object-literals-in-es6-a9d

23
Objekt.assign()

• Object.assign() kopiert die Werte aller Objektliterale in das erste


Objektliteral
• Es wird das neue Zielobjekt zurückgegeben.
• Gleiche Attribute werden überschrieben
• Hinweis: es wird kein neues Objekt angelegt!

var target = { a: 1, b: 2 };
var source = { b: 4, c: 5 };
var returnedTarget = Object.assign(target, source);
console.log(target)
console.log(returnedTarget)

Beuth Hochschule für Technik Berlin – University of Applied Sciences 24


Arrow-Funktionen

Beuth Hochschule für Technik Berlin – University of Applied Sciences 25


Arrow-Funktionen
• Im Deutschen: Pfeilfunktionen
• Lambda-Ausdrücke, die funktionale Programmierung unterstützen
• Definition von Funktionen mit =>
• Ähnlich wie in C#, Java8 und CoffeeScript
• Verkürzt die Schreibweise von Funktionen deutlich
• Aber: auch Lesbarkeit geht etwas verloren
• Auch in Java möglich

// ES5
var x = function(x, y) {
return x * y;
}

// ES6
const x = (x, y) => x * y;

Beuth Hochschule für Technik Berlin – University of Applied Sciences 26


Arrow-Funktionen
• Die Syntax wird bestimmt durch die
• Anzahl der Parameter, die übergeben werden
• Die Anzahl der Befehle in der Funktion

// Mehrere Parameter und mehrere Befehle


(param1, param2, …, paramN) => { statements }

// Mehrere Parameter und 1 Befehl


(param1, param2, …, paramN) => expression

// gleich zu: => { return expression; }


(param1, param2, …, paramN) => { return expression; }

Beuth Hochschule für Technik Berlin – University of Applied Sciences 27


Arrow-Funktionen
• Wenn keine Parameter übergeben werden, müssen runde Klammern gesetzt
werden

() => { statements }

// Klammern sind optional, wenn nur ein Parametername vorhanden


ist:

(singleParam) => { statements }


singleParam => { statements }

Beuth Hochschule für Technik Berlin – University of Applied Sciences 28


Arrow-Funktionen
• Sehr viele unterschiedliche Varianten für Nutzung
• Map-Funktion von Array: wendet auf jedes Element des Arrays die
bereitgestellte Funktion an und gibt das Ergebnis in einem neuen Array
zurück.

const materials = [ 'Hydrogen', 'Helium', 'Lithium', 'Beryllium'];

console.log(materials.map(material => material.length));


// expected output: Array [8, 6, 7, 9]

• Der Body kann eingeklammert werden, um ein Objektliteral-Ausdruck


zurück zu geben

params => ({foo: bar})

Beuth Hochschule für Technik Berlin – University of Applied Sciences 29


Arrow-Funktionen
• Rest Parameter und Default Parameter werden unterstützt

(param1, param2, ...rest) => { statements }

(param1 = defaultValue1, param2, …, paramN = defaultValueN) => {


statements }

Beuth Hochschule für Technik Berlin – University of Applied Sciences 30


Arrow-Funktionen
• 3 mögliche Umsetzungen mit identischem Ergebnis

var elements = [
"Hydrogen",
"Helium",
"Lithium",
"Beryllium"
];

elements.map(function(element) {
return element.length
}); // [8, 6, 7, 9]

elements.map(element => {
return element.length
}); // [8, 6, 7, 9]

elements.map(({length}) => length); // [8, 6, 7, 9]

Beuth Hochschule für Technik Berlin – University of Applied Sciences 31


Arrow-Funktionen: this
• In JavaScript definiert jede Funktion sein eigenen this-Kontext
• Im nachfolgenden Code gibt es ein this im Person und ein im setInterval()
• Daher ist this.age in setInterval() nicht definiert

function Person() {
this.age = 0;

setInterval(function growUp() {
this.age++;
console.log("Age: " + this.age)
}, 1000);
}

var p = new Person();

Quelle: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions/Pfeilfunktionen

32
Arrow-Funktionen: this
• In ECMAScript 5 konnte das über eine lokale Variable behoben werden
• Die Umsetzung ist aber nicht wirklich gut

function Person() {
that = this;
this.age = 0;

setInterval(function growUp() {
that.age++;
console.log("Age: " + that.age)
}, 1000);
}

var p = new Person();

Quelle: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions/Pfeilfunktionen

33
Arrow-Funktionen: this
• Arrow-Funktionen definieren kein eigenen this-Kontext
• Daher kann die Arrow-Funktion auf das this von Person zugreifen
• Arrow-Funktionen haben keinen eigenen this-Kontext
• Sie verwenden den this-Kontext des Umgebungskontextes

function Person(){
this.age = 0;

setInterval(() => {
this.age++;
console.log("Age: " + this.age)
}, 1000);
}

var p = new Person();

Quelle: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions/Pfeilfunktionen

34
Arrow-Funktionen: this in Java
• Lambda-Ausdrücke behandeln this-Kontext anders als Interface-Instanzen!

private String value = "In Lambda-Klasse"; @FunctionalInterface


... public interface Foo
Foo fooIC = new Foo() { {
String value = "Inner class value"; String method(String string);
@Override }
public String method(String string)
{
return this.value;
}
};
String resultIC = fooIC.method("");

Foo fooLambda = parameter -> {


String value = "Lambda value";
return this.value;
};
String resultLambda = fooLambda.method("");
System.out.println("Results: resultIC = " + resultIC + ", resultLambda = " + resultLambda);

35
Arrow-Funktionen
• Arrow-Funktionen sollten eher nicht in Objektliteralen angewandt werden,
weil der this-Kontext unklar ist

var obj = {
i: 10,
b: () => console.log(this.i, this),
c: function() {
console.log( this.i, this)
}
}
obj.b(); // gibt undefined, Window {...} aus (oder das globale Objekt)
obj.c(); // gibt 10, Object {...} aus

Quelle: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions/Pfeilfunktionen

36
Module

Beuth Hochschule für Technik Berlin – University of Applied Sciences 37


Module in JavaScript
• Es gibt unterschiedliche Arten von Modulen, die von Laufzeitumgebung
abhängen
• Native JavaScript Module
• Definiert in ECMAScript 6
• Teil der Programmiersprache
• Einbinden über „import“
• Export über „export“
• Modul wird nur einmal instanziiert (→ Singleton)
• CommonJS Module
• Für node.js
• Serverseitig
• Einbinden über „require“
• Export über „module.exports“
• Es werden Kopien von den Objekten zurückgegeben
• Weitere: Async Module Definition, Universal Module Definition

Beuth Hochschule für Technik Berlin – University of Applied Sciences 38


Native Module
• Unterteilen von JavaScript-Funktionen in Module möglich
• Unterteilung von Modulen auf unterschiedliche Dateien
• Module können Konstanten oder Funktionen exportieren
• Mit „import“ können exportierte Referenzen importiert werden

export const name = "Manfred";

export function meinAlter()


{
return 20;
}

import {name, meinAlter} from "./Testmodule.js"

console.log("Name: " + name);


console.log("Alter: " + meinAlter());

Beuth Hochschule für Technik Berlin – University of Applied Sciences 39


Native Module
• Wenn ein Modul mehrfach importiert wird, wird der Code nur einmal
ausgewertet und ausgeführt
• Danach erhalten alle die gleichen Export-Referenzen → wie ein Singleton
• Achtung: potentielle Seiteneffekte!

export let admin = {


name: "John"
};

import {admin} from './admin.js';


admin.name = "Pete";

import {admin} from './admin.js';


alert(admin.name); // Pete

// Beide verwenden die gleiche Referenz, Änderungen werden in beiden


// Modulen übernommen

Beuth Hochschule für Technik Berlin – University of Applied Sciences 40


Native Module
• Singleton-Eigenschaft von Modulen hat Vor- und Nachteile
• Zentrale Konfigurationsmodule nutzen gleiche Daten
• Aber Objekte können von allen geändert werden
• Schutz der Daten muss über Funktionen umgesetzt werden (keine
Objektreferenzen exportieren)
• Statische Prüfung der Exports (zur Compile-Zeit)
• Damit in Node.js natives JavaScript-Module geladen werden können, muss
Projekt ein Modul sein
• Dazu muss in package.json folgender Eintrag vorhanden sein.
• Anmerkung: ES6-Module sind derzeit unter node.js „experimental“

{
"type": "module"
}

Beuth Hochschule für Technik Berlin – University of Applied Sciences 41


CommonJS Module
• CommonJS war Projekt, um Konventionen zur Definition von Modulen in
JavaScript festzulegen
• War noch vor ECMA6
• Browser unterstützen diese Module nicht, müssen vorher über einen
Transpiler in Standard-JavaScript überführt werden
• Werden vor allem in Node.js verwendet
• Erkennbar an require() und module.exports (im Vergleich zu ES6-Modulen)

Beuth Hochschule für Technik Berlin – University of Applied Sciences 42


CommonJS Module
• Module werden als Objekte exportiert (in diesem Fall Funktionsprototyp)

const name = "Manfred";

function meinAlter()
{
return 20;
}

module.exports = {name, meinAlter}

const modul = require('./NodeModule')

console.log("Name: " + modul.name);


console.log("Alter: " + modul.meinAlter());

Beuth Hochschule für Technik Berlin – University of Applied Sciences 43


CommonJS Module
• Es gibt zwei Varianten zum Exportieren von Objekten: exports und
module.exports
const name = "Manfred";
exports = name;

function meinAlter()
{
return 20;
}
module.exports = {name, meinAlter}

• module ist ein einfaches JavaScript-Objekt, dass für den Zugriff auf das
Modul angelegt wird
• exports ist eine JavaScript-Variable, der jede Referenzen zugewiesen
werden können, die das Modul zurückgeben soll
• Wenn beides verwendet wird, entscheidet module.exports, was tatsächlich
zurückgegeben wird → verwenden Sie eher module.exports

Beuth Hochschule für Technik Berlin – University of Applied Sciences 44


CommonJS Module
• module.exports kann Attribute und Funktionen als Objektliteral zurückgeben
• Dabei können auch Namen für die exportierten Objekte vergeben werden

const name = "Manfred"; exports.a = 1


exports.b = 2
function meinAlter() exports.c = 3
{
return 20; • Beim Import können auch die
} Referenzen explizit importiert werden
module.exports = {
meinName: name, const { a, b, c } = require('./uppercase.js')
meinAlter: meinAlter
}

Beuth Hochschule für Technik Berlin – University of Applied Sciences 45


CommonJS Module
• Wenn diese Module verwendet werden, darf im package.json nicht das
Modul-Attribut enthalten sein!
• Ansonsten kompiliert die Anwendung nicht

{
"type": "module"
}

Beuth Hochschule für Technik Berlin – University of Applied Sciences 46


Asynchrone Aufrufe

Beuth Hochschule für Technik Berlin – University of Applied Sciences 47


Node.js: asynchrone Aufrufe
• Bei Programmschritten, die länger dauern können, sind synchrone Aufrufe
problematisch
• Blockieren die gesamte Anwendung
• Prozesse können nicht verteilt werden auf mehrere CPUs
• Daher werden aufwändige oder länger laufende Verarbeitungsschritte
asynchron ausgeführt
• Asynchrone Callback-Funktionen
• Promise
• Asynchronen Funktionen

Beuth Hochschule für Technik Berlin – University of Applied Sciences 48


Callback-Funktionen
• Funktion wird aus einer Funktion heraus aufgerufen

let meinCallback = function () {


console.log ("in Callback");
}

let aufrufendeFunktion = function (callback) {


console.log("aufrufende Funktion");
callback();
aufrufende Funktion
} in Callback

aufrufendeFunktion(meinCallback);

• Callback-Funktion ist zunächst nicht asynchron


• Callback-Funktionen werden jedoch häufig an asynchrone Funktionen
übergeben

Beuth Hochschule für Technik Berlin – University of Applied Sciences 49


Callback-Funktionen
• Beispiel: Starten eines Servers mit Callback-Funktion

var http = require('http');

http.createServer(function (req, res) {


res.writeHead(200, {'Content-Type': 'text/html'});
res.end('Hello World!');
}).listen(8080);

console.log(„Hallo“)

• createServer startet einen Server und bekommt eine Callback-Methode


übergeben, die alle Anfragen an den Server bearbeitet
• Immer wenn eine Seite vom Server angefragt wird, werden das Request-
und Response-Objekt an die Methode übergeben
• Die Konsolenausgabe „Hallo“ unmittelbar nach dem Ausführen des
Programms ausgegeben, noch bevor der Server gestartet wurde

Beuth Hochschule für Technik Berlin – University of Applied Sciences 50


Callback-Funktionen
• Beispiel: Anhängen von Text an eine Datei

var fs = require('fs');

fs.appendFile('mynewfile1.txt', 'Hello content!', function (err) {


if (err)
throw err;
console.log('Saved!');
});

• appendFile bekommt den Dateinamen der zu ändernden Datei, den


anzuhängenden Text und eine Callback-Funktion, die ausgeführt wird, wenn
das Anhängen des Textes abgeschlossen ist
• Wenn beim Anhängen des Textes ein Fehler aufgetreten ist, wird der Fehler
an die Funktion übergeben
• Ansonsten ist das Fehlerobjekt leer

Beuth Hochschule für Technik Berlin – University of Applied Sciences 51


Promise
• Häufig werden Callback-Methoden in Verbindung mit Promise verwendet
• Umsetzung von asynchronen, langlaufenden, schrittweisen Prozessen über
klassische Ansätze (z.B. Event-Listener) sehr aufwändig
• Beispiel: Aufrufen einer URL auf einem Server
Const url = „http://www.restservice.de/anfrage“;
const xhr = new XMLHttpRequest(url);
xhr.addEventListener ("readystatechange", (url) => {
if (xhr.readyState === 4) {
console.log (xhr.responseText);
}
})
xhr.open ("GET", url);
xhr.send();

• Es wird ein Request angelegt und ein Event-Listener angehangen, der


aufgerufen wird, wenn das Ergebnis da ist
• Anschließend wird die Verbindung geöffnet und die Anfrage abgeschickt

Beuth Hochschule für Technik Berlin – University of Applied Sciences 52


Promise
• Verwendung von Event-Listener für einzelne Abfrage noch ok, für
Sequenzen von Anfragen schnell unübersichtlich
const url = "../fetch.json";
const url2 = "../file.json";
const url3 = "../data.json";
const xhr = new XMLHttpRequest(url);
xhr.addEventListener ("readystatechange", (url) => {
if (xhr.readyState === 4) {
console.log (xhr.responseText);
const xhr2 = new XMLHttpRequest(url2);
xhr2.addEventListener ("readystatechange", (url2) => {
if (xhr2.readyState === 4) {
const xhr3 = new XMLHttpRequest(url3);
xhr3.addEventListener ("readystatechange", (url3) => {
});

}
});
xhr2.open ("GET", url2);
xhr2.send();
}});
xhr.open ("GET", url);
xhr.send();

Beuth Hochschule für Technik Berlin – University of Applied Sciences 53


Promise
• Ineinander verschachtelte Callback-Methoden werden schnell
unübersichtlich → man nennt es „Callback-Hell“
• Promise: Objekte, die das Ergebnis einer asynchronen Aktion abwarten und
dann zurückgeben, wenn die Daten da sind oder ein Fehler aufgetreten ist
• Vergleichbar zu Future in Java

Beuth Hochschule für Technik Berlin – University of Applied Sciences 54


Promise
• Einfaches Beispiel:
• Promise wird sofort gestartet (erste Ausgabe),
• setTimeout blockt den Callback für 1 Sekunde, Ausführung wird fortgesetzt
(zweite Ausgabe außerhalb des Promise)
• Nach einer Sekunde schließt der Promise ab mit resolve

let promise = new Promise(function (resolve, reject) {


console.log("Im Promise")
setTimeout(() => {
console.log("Now resolve it.")
resolve("done")
},1000);
});

console.log("Nach dem Promise")

Beuth Hochschule für Technik Berlin – University of Applied Sciences 55


Promise
• Um Anwendung nach Abschluss des Promise weiterzuführen, können per
then() ein Callback für den Erfolgsfall und einen für den Fehlerfall übergeben
werden
var testFunktion = function (testZahl) {
return new Promise(function (resolve, reject) {
console.log("Im Promise")
setTimeout(() => {
if (testZahl == 1) {
resolve("done")
}
else {
reject("Ist nicht 1")
}
}, 1000);
}).then(
() => console.log("Success"),
() => console.log("Fehler")
);
}

testFunktion(2)

Beuth Hochschule für Technik Berlin – University of Applied Sciences 56


Promise-Verkettung
• Promises können über then() miteinander verkettet werden, um immer
wieder asynchrone Aufrufe (fetch() ) auszuführen

fetch (url).then ( function (response) {


return response.json();
}).then ( function (data) {
console.log ("url 1 " + data)
}).then (fetch (url2).then (function (response) {
return response.json();
}).then (function (data) {
console.log ("url 2 " + data)
}).then (fetch (url3).then (function (response) {
return response.json();
}).then (function (data) {
console.log ("url 3 " + data)
})
))

Beuth Hochschule für Technik Berlin – University of Applied Sciences 57


Promise: Error-Handling
• Error-Handling in JavaScript ähnlich wie in Java
• Es werden Fehlerobjekte (Error-Object) mit throw geworfen
• Es werden Exceptions per catch() gefangen

function myApiFunc(callback) {
try {
doSomeAsynchronousOperation((err) => {
if (err) { Error-Object
throw (err);
}
/* continue as normal */
});
} catch (ex) {
callback(ex); Exception
}
}

Quelle: https://www.joyent.com/node-js/production/design/errors

Beuth Hochschule für Technik Berlin – University of Applied Sciences 58


Promise: Exceptions
• Tritt bei einem Promise eine Exception auf, wird diese nicht durch ein
synchrones try-catch gefangen

function example() {
return new Promise((resolve, reject) => {
throw „Fehler“
});
}

try {
example().then(r => console.log(`.then(${r})`));
} catch (e) {
console.error(`try/catch(${e})`);
}

(node:12052) UnhandledPromiseRejectionWarning: test reject


(node:12052) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated …
(node:12052) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In …

Beuth Hochschule für Technik Berlin – University of Applied Sciences 59


Exception-Handling bei Promise
• Bei einem Promise muss die Catch-Methode vom Promise verwendet
werden

function example() {
return new Promise((resolve, reject) => {
reject("test reject");
});
}

try {
example()
.then(r => console.log(`.then(${r})`))
.catch(e => console.error(`.catch(${e})`));
} catch (e) {
console.error(`try/catch(${e})`);
}

Beuth Hochschule für Technik Berlin – University of Applied Sciences 60


Promise-Verkettung
• Exception-Handling sauberer als bei Callbacks

doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);

• Bei Callback müssten ineinander gestaffelte if-Statements verwendet werden


mit jeweils separaten Catch-Blöcken
• Then liefert wieder ein Promise zurück
• Gestaffelte Promise reichen das Reject hoch → nur ein Catch reicht

Beuth Hochschule für Technik Berlin – University of Applied Sciences 61


Exception-Handling bei Promise
• Alternativ zum catch() kann auch beim then() ein Error-Callback verwendet
werden
var testFunktion = function (testZahl) {
return new Promise(function (resolve, reject) {
if (testZahl == 1) {
resolve("done")
}
else if (testZahl == 2) {
throw new Error("Ein Fehler!")
}
else {
reject("Ist nicht 1")
}
}).then(
() => console.log("Success"),
() => console.log("Fehler")
).catch(err => console.log("Warum denn der Fehler"))
}

testFunktion(2)

Beuth Hochschule für Technik Berlin – University of Applied Sciences 62


Promise: Exception-Handling
• Insbesondere bei verschachtelten then()-Aufrufen sollte zum Schluss ein
catch() angehangen werden
• Fehler werden von den Promises weitergereicht bis zum ersten catch()
• Innerhalb der Promises sollten eher keine Try-Catch-Blöcke verwendet
werden
• Es muss unterschieden werden, welche Exception synchron und welche
asynchron geworfen werden können
• Bei synchronen Exceptions muss der Promise-Aufruf noch in einen Try-
Catch-Block

var testFunktion = function (testZahl) {


throw new Error("vor dem promise")
return new Promise(function (resolve, reject) {
if (testZahl == 1) {
resolve("done")
}

Beuth Hochschule für Technik Berlin – University of Applied Sciences 63


Async-Funktionen
• Der Umgang mit Promise und Callback-Funktionen ist für viele nicht so
angenehm
• Mit Async-Funktionen und „await“ können asynchrone Aufrufe wie synchrone
Aufrufe verwendet werden

function resolveAfter1Second() {
return new Promise(resolve => {
setTimeout(() => {
console.log("Im Promise")
resolve('resolved');
}, 1000);
});
}

async function asyncCall() {


console.log('Vor der Asyn Funtion');
const result = await resolveAfter1Second();
console.log("Nach dem Async: " + result);
}

asyncCall();

Beuth Hochschule für Technik Berlin – University of Applied Sciences 64


Async-Funktionen
• Async-Funktionen geben immer ein Promise zurück!
• Um Rückgabewerte auszuwerten, muss ein then()-Block verwendet werden

async function hello()


{
return "Hello"
};

console.log("Result: " + hello())

hello().then((value) => console.log("Return value: " + value))

Beuth Hochschule für Technik Berlin – University of Applied Sciences 65


Async-Funktionen
Beispiele für die Definition und Nutzung von Async-Funktionen
• Funktionsvariable

let hello = async function() { return "Hello" };


hello();

• Pfeilfunktion
let hello = async () => { return "Hello" };

• Rückgabewert über then() ausgeben


hello().then((value) => console.log(value))
hello().then(console.log)

Beuth Hochschule für Technik Berlin – University of Applied Sciences 66


Async-Funktionen: Exception-Handling
• Da Async-Funktionen ein Promise zurückgeben und asynchron ausgeführt
werden, kann kein try-catch verwendet werden, sondern wird das catch() an
das Promise angehangen
var testFunktion = function (testZahl) {
return new Promise(function (resolve, reject) {
console.log("Do the long process")
reject("Hier ist ein Fehler")
}).then(
() => {return "Done"}
)
}

async function hello() {


let ergebnis = await testFunktion(1)
return ergebnis
};

hello().then(
(value) => console.log("Return value: " + value)
).catch(
e => console.log(e)
)

67
Async-Funktionen: Exception-Handling
• Wenn mehrere langlaufende Funktionsaufrufe ausgeführt und abgewartet
werden sollen, kann Promise.all() verwendet werden

async function displayContent() {


let coffee = fetchAndDecode('coffee.jpg', 'blob');
let tea = fetchAndDecode('tea.jpg', 'blob');
let description = fetchAndDecode('description.txt', 'text');

let values = await Promise.all([coffee, tea, description]);


68
Callbacks und Asynchrone Funktionen
bei REST-Services

69
Service-Funktion mit Callback-Funktionen
• Bei der Nutzung von Callback-Funktionen muss in der Regel die aufrufende
Callback-Funktion zum Abschluss aufgerufen werden
• Die Callback-Funktionen können z.T. komplex geschachtelt sein

function getPublicUsers(callback) {
User.find(function (err, users) {
if (err) {
logger.error("An Error occured finding all users: " + err);
return callback(err, null);
}
else {
console.log("got users: " + users)
return callback(null, users);
}
})
}

70
Service-Funktion mit Asynchroner Funktione
• Beim Aufruf von asynchronen Funktionen muss in der Regel ein „await“
verwendet werden, damit das Ergebnis abgewartet wird
• Die gesamte Funktion muss dann auch eine asynchrone Funktion sein!

async function getPublicUsersAsync() {


var users = await User.find();
return users;
}

71
Route mit Callback-Funktionen
• Bei Callback-Funktionen ist einfache Übergabe von Fehlermeldungen üblich

router.get('/', function (req, res) {

userService.getPublicUsers(function (err, result) {


if (result) {
res.status(200).send(Object.values(result));
}
else {
res.status(404).send("Invalid result: " + err);
}
}
);
});

72
Route mit Asynchroner Funktione
• Umsetzung ähnlich wie beim Service

router.get('/async', async function (req, res) {

var users = await userService.getPublicUsersAsync();


res.status(200).send(Object.values(users));

});

73
Async-Funktionen
• Async-Funktionen erleichtern auf den ersten Blick den Code, weil
asynchrone Funktion aussehen wie synchrone Funktionen
• Doch der Nachteil ist, dass die eigene Funktionsausführung geblockt wird →
das kann die Performance der eigenen Anwendung beeinträchtigen
• Wenn das Promise gar nicht antwortet (weil der Service offline ist) kann die
Anwendung blockiert werden

Beuth Hochschule für Technik Berlin – University of Applied Sciences 74


Weiter Tipps

Beuth Hochschule für Technik Berlin – University of Applied Sciences 75


Mehrere Rückgabeparameter
• Manchmal wäre es hilfreich, mehrere Rückgabewerte bei einer Methode
zurückzugeben
• Das kann man machen, indem man einen Array zurückgibt und bei der
aufrufenden Methode direkt Variablen zuweist

login("user", "passwort")

function login(userID, password)


{
const [err,user] = authenticate(userID,password)

if(err)
{
function authenticate(userID, password)
console.log("Es ist ein Fehler aufgetreten: " + err)
{
}

else
error = "Passwort ist falsch!"
{
user = null
console.log("Login erfolgreich.")
return [error,user]
}
}
}

Beuth Hochschule für Technik Berlin – University of Applied Sciences 76

Das könnte Ihnen auch gefallen