Skip to content
Mithril.js 2
Main Navigation AnleitungAPI

Deutsch

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Deutsch

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Aussehen

Sidebar Navigation

API

Kern-API

m(selector, attributes, children)

render(element, vnodes)

mount(root, component)

route(root, defaultRoute, routes)

request(options)

parseQueryString(string)

buildQueryString(object)

buildPathname(object)

parsePathname(string)

trust(html)

fragment(attrs, children)

redraw()

censor(object, extra)

Optionale API

stream()

Anleitung

Auf dieser Seite

request(options) ​

Beschreibung ​

Führt XHR- (auch bekannt als AJAX-) Anfragen aus und gibt ein Promise zurück.

javascript
m.request({
  method: 'PUT',
  url: '/api/v1/users/:id',
  params: { id: 1 },
  body: { name: 'test' },
}).then(function (result) {
  console.log(result);
});

Signatur ​

promise = m.request(options)

ArgumentTypeRequiredDescription
optionsObjectYesDie Anfrageoptionen, die übergeben werden.
options.methodStringNoDie zu verwendende HTTP-Methode. Gültige Werte sind: GET, POST, PUT, PATCH, DELETE, HEAD oder OPTIONS. Standardwert ist GET.
options.urlStringYesDer Pfadname, an den die Anfrage gesendet werden soll. Optional können Werte aus options.params in die URL interpoliert werden.
options.paramsObjectNoDie Daten, die in die URL interpoliert und/oder als Query-String serialisiert werden sollen.
options.bodyObjectNoDie Daten, die im Anfragekörper serialisiert werden sollen (für andere Anfragearten als GET).
options.asyncBooleanNoGibt an, ob die Anfrage asynchron erfolgen soll. Standardwert ist true.
options.userStringNoEin Benutzername für die HTTP-Authentifizierung. Standardwert ist undefined.
options.passwordStringNoEin Passwort für die HTTP-Authentifizierung. Standardwert ist undefined. Diese Option dient der XMLHttpRequest-Kompatibilität, sollte aber vermieden werden, da sie das Passwort im Klartext über das Netzwerk sendet.
options.withCredentialsBooleanNoGibt an, ob Cookies an Drittanbieter-Domains gesendet werden sollen. Standardwert ist false.
options.timeoutNumberNoDie maximale Dauer der Anfrage in Millisekunden, bevor sie automatisch beendet wird. Standardwert ist undefined.
options.responseTypeStringNoDer erwartete Typ der Antwort. Standardwert ist "", wenn extract definiert ist, ansonsten "json". Wenn responseType: "json", wird intern JSON.parse(responseText) ausgeführt.
options.configxhr = Function(xhr)NoErmöglicht den Zugriff auf das zugrunde liegende XMLHttpRequest-Objekt für grundlegende Konfigurationen und optionalen Austausch (durch Rückgabe eines neuen XHR-Objekts).
options.headersObjectNoHeader, die der Anfrage vor dem Senden hinzugefügt werden sollen (werden direkt vor options.config angewendet).
options.typeany = Function(any)NoEin Konstruktor, der auf jedes Objekt in der Antwort angewendet werden soll. Standardwert ist die Identitätsfunktion.
options.serializestring = Function(any)NoEine Serialisierungsmethode, die auf body angewendet werden soll. Standardwert ist JSON.stringify oder, falls options.body eine Instanz von FormData oder URLSearchParams ist, die Identitätsfunktion (d. h. function(value) {return value}).
options.deserializeany = Function(any)NoEine Deserialisierungsmethode, die auf xhr.response oder normalisiertes xhr.responseText angewendet werden soll. Standardwert ist die Identitätsfunktion. Wenn extract definiert ist, wird deserialize übersprungen.
options.extractany = Function(xhr, options)NoEin Hook, um festzulegen, wie die XMLHttpRequest-Antwort interpretiert werden soll. Nützlich für die Verarbeitung von Antwortdaten sowie zum Lesen von Headern und Cookies. Standardmäßig ist dies eine Funktion, die options.deserialize(parsedResponse) zurückgibt und eine Ausnahme auslöst, wenn der Antwortstatuscode des Servers einen Fehler signalisiert oder die Antwort syntaktisch ungültig ist. Wenn ein benutzerdefinierter Extraktions-Callback bereitgestellt wird, ist der xhr-Parameter die XMLHttpRequest-Instanz, die für die Anfrage verwendet wurde, und options das Objekt, das an den m.request-Aufruf übergeben wurde. Darüber hinaus wird deserialize übersprungen, und der vom Extraktions-Callback zurückgegebene Wert wird bei Auflösung des Promises unverändert übernommen.
options.backgroundBooleanNoWenn false, werden gemountete Komponenten nach Abschluss der Anfrage neu gezeichnet. Wenn true, nicht. Standardwert ist false.
returnsPromiseEin Promise, das mit den Antwortdaten aufgelöst wird, nachdem diese durch die Methoden extract, deserialize und type verarbeitet wurden. Wenn der Antwortstatuscode einen Fehler anzeigt, wird das Promise abgewiesen. Dies kann jedoch durch Festlegen der Option extract verhindert werden.

promise = m.request(url, options)

ArgumentTypeRequiredDescription
urlStringYesDer Pfadname, an den die Anfrage gesendet werden soll. options.url überschreibt diesen Wert, falls vorhanden.
optionsObjectNoDie Anfrageoptionen, die übergeben werden.
returnsPromiseEin Promise, das mit den Antwortdaten aufgelöst wird, nachdem diese durch die Methoden extract, deserialize und type verarbeitet wurden.

Diese zweite Form ist im Wesentlichen äquivalent zu m.request(Object.assign({url: url}, options)), nur dass sie intern nicht von der globalen ES6-Funktion Object.assign abhängt.

So lesen Sie Signaturen

Funktionsweise ​

Das Hilfsprogramm m.request ist eine schlanke Abstraktion über XMLHttpRequest und ermöglicht das Senden von HTTP-Anfragen an Remote-Server, um Daten zu speichern und/oder abzurufen.

javascript
m.request({
  method: 'GET',
  url: '/api/v1/users',
}).then(function (users) {
  console.log(users);
});

Ein Aufruf von m.request gibt ein Promise zurück und löst nach Abschluss der Promise-Kette eine Neudarstellung aus.

Standardmäßig geht m.request davon aus, dass die Antwort im JSON-Format vorliegt und parst sie in ein JavaScript-Objekt (oder Array).

Wenn der HTTP-Antwortstatuscode einen Fehler signalisiert, wird das zurückgegebene Promise abgewiesen. Die Bereitstellung eines Extract-Callbacks verhindert die Abweisung des Promises.

Typische Verwendung ​

Hier ist ein Beispiel einer Komponente, die m.request verwendet, um Daten von einem Server abzurufen.

javascript
var Data = {
  todos: {
    list: [],
    fetch: function () {
      m.request({
        method: 'GET',
        url: '/api/v1/todos',
      }).then(function (items) {
        Data.todos.list = items;
      });
    },
  },
};

var Todos = {
  oninit: Data.todos.fetch,
  view: function (vnode) {
    return Data.todos.list.map(function (item) {
      return m('div', item.title);
    });
  },
};

m.route(document.body, '/', {
  '/': Todos,
});

Nehmen wir an, dass eine Anfrage an die Server-URL /api/items ein Array von Objekten im JSON-Format zurückgibt.

Wenn m.route am Ende aufgerufen wird, wird die Komponente Todos erstellt. oninit wird aufgerufen, wodurch m.request aufgerufen wird. Dies ruft asynchron ein Array von Objekten vom Server ab. "Asynchron" bedeutet, dass JavaScript weiterhin anderen Code ausführt, während es auf die Antwort vom Server wartet. In diesem Fall bedeutet dies, dass fetch zurückkehrt und die Komponente mit dem ursprünglichen leeren Array als Data.todos.list gerendert wird. Sobald die Anfrage an den Server abgeschlossen ist, wird das Array von Objekten items Data.todos.list zugewiesen und die Komponente wird erneut gerendert, wodurch eine Liste von <div>s mit den Titeln der einzelnen todos erzeugt wird.

Fehlerbehandlung ​

Wenn eine Nicht-file:-Anfrage mit einem anderen Status als 2xx oder 304 zurückkehrt, wird sie mit einem Fehler abgewiesen. Dieser Fehler ist eine normale Error-Instanz, jedoch mit einigen speziellen Eigenschaften.

  • error.message enthält den rohen Antworttext.
  • error.code enthält den Statuscode selbst.
  • error.response enthält die geparste Antwort, wobei options.extract und options.deserialize wie bei normalen Antworten verwendet werden.

Dies ist in vielen Fällen nützlich, in denen Fehler selbst Informationen enthalten, die Sie berücksichtigen können. Wenn Sie feststellen möchten, ob eine Sitzung abgelaufen ist, können Sie if (error.code === 401) return promptForAuth().then(retry) ausführen. Wenn Sie auf den Drosselungsmechanismus einer API stoßen und diese einen Fehler mit einem "timeout": 1000 zurückgibt, können Sie ein setTimeout(retry, error.response.timeout) ausführen.

Ladeicons und Fehlermeldungen ​

Hier ist eine erweiterte Version des vorherigen Beispiels, die eine Ladeanzeige und eine Fehlermeldung implementiert:

javascript
var Data = {
  todos: {
    list: null,
    error: '',
    fetch: function () {
      m.request({
        method: 'GET',
        url: '/api/v1/todos',
      })
        .then(function (items) {
          Data.todos.list = items;
        })
        .catch(function (e) {
          Data.todos.error = e.message;
        });
    },
  },
};

var Todos = {
  oninit: Data.todos.fetch,
  view: function (vnode) {
    return Data.todos.error
      ? [m('.error', Data.todos.error)]
      : Data.todos.list
      ? [
          Data.todos.list.map(function (item) {
            return m('div', item.title);
          }),
        ]
      : m('.loading-icon');
  },
};

m.route(document.body, '/', {
  '/': Todos,
});

Es gibt einige Unterschiede zwischen diesem Beispiel und dem vorherigen. Hier ist Data.todos.list am Anfang null. Außerdem gibt es ein zusätzliches Feld error zum Speichern einer Fehlermeldung, und die Ansicht der Komponente Todos wurde geändert, um eine Fehlermeldung anzuzeigen, falls eine vorhanden ist, oder ein Ladeicon anzuzeigen, falls Data.todos.list kein Array ist.

Dynamische URLs ​

Anfrage-URLs können Interpolationen enthalten:

javascript
m.request({
  method: 'GET',
  url: '/api/v1/users/:id',
  params: { id: 123 },
}).then(function (user) {
  console.log(user.id); // logs 123
});

Im obigen Code wird :id durch die Daten aus dem params-Objekt ersetzt, wodurch die Anfrage zu GET /api/v1/users/123 wird.

Interpolationen werden ignoriert, wenn keine übereinstimmenden Daten in der Eigenschaft params vorhanden sind.

javascript
m.request({
  method: 'GET',
  url: '/api/v1/users/foo:bar',
  params: { id: 123 },
});

Im obigen Code wird die Anfrage zu GET /api/v1/users/foo:bar?id=123

Abbrechen von Anfragen ​

Manchmal ist es wünschenswert, eine Anfrage abzubrechen. Beispielsweise möchten Sie in einem Autocompleter-/Typeahead-Widget sicherstellen, dass nur die letzte Anfrage abgeschlossen wird, da Autocompleter in der Regel mehrere Anfragen auslösen, während der Benutzer tippt, und HTTP-Anfragen aufgrund der unvorhersehbaren Natur von Netzwerken möglicherweise nicht in der richtigen Reihenfolge abgeschlossen werden. Wenn eine andere Anfrage nach der zuletzt gesendeten Anfrage abgeschlossen wird, würde das Widget weniger relevante (oder potenziell falsche) Daten anzeigen, als wenn die zuletzt gesendete Anfrage als letzte abgeschlossen würde.

m.request() legt sein zugrunde liegendes XMLHttpRequest-Objekt über den Parameter options.config offen, wodurch Sie einen Verweis auf dieses Objekt speichern und bei Bedarf seine abort-Methode aufrufen können:

javascript
var searchXHR = null;
function search() {
  abortPreviousSearch();

  m.request({
    method: 'GET',
    url: '/api/v1/users',
    params: { search: query },
    config: function (xhr) {
      searchXHR = xhr;
    },
  });
}
function abortPreviousSearch() {
  if (searchXHR !== null) searchXHR.abort();
  searchXHR = null;
}

Datei-Uploads ​

Um Dateien hochzuladen, müssen Sie zuerst einen Verweis auf ein File-Objekt erhalten. Der einfachste Weg, dies zu tun, ist über ein <input type="file">.

javascript
m.render(document.body, [m('input[type=file]', { onchange: upload })]);

function upload(e) {
  var file = e.target.files[0];
}

Der obige Code rendert ein Dateieingabefeld. Wenn ein Benutzer eine Datei auswählt, wird das onchange-Ereignis ausgelöst, das die Funktion upload aufruft. e.target.files ist eine Liste von File-Objekten.

Als Nächstes müssen Sie ein FormData-Objekt erstellen, um eine mehrteilige Anfrage (Multipart-Anfrage) zu erstellen. Dies ist eine speziell formatierte HTTP-Anfrage, mit der Dateidaten im Anfragetext übertragen werden können.

javascript
function upload(e) {
  var file = e.target.files[0];

  var body = new FormData();
  body.append('myfile', file);
}

Als Nächstes müssen Sie m.request aufrufen und options.method auf eine HTTP-Methode setzen, die einen Body verwendet (z. B. POST, PUT, PATCH), und das FormData-Objekt als options.body verwenden.

javascript
function upload(e) {
  var file = e.target.files[0];

  var body = new FormData();
  body.append('myfile', file);

  m.request({
    method: 'POST',
    url: '/api/v1/upload',
    body: body,
  });
}

Vorausgesetzt, der Server ist für die Annahme von Multipart-Anfragen konfiguriert, werden die Dateiinformationen dem Schlüssel myfile zugeordnet.

Mehrere Datei-Uploads ​

Es ist möglich, mehrere Dateien in einer Anfrage hochzuladen. Dadurch wird der Stapel-Upload (Batch-Upload) atomar, d. h. es werden keine Dateien verarbeitet, wenn während des Uploads ein Fehler auftritt, sodass es nicht möglich ist, nur einen Teil der Dateien zu speichern. Wenn Sie im Falle eines Netzwerkausfalls so viele Dateien wie möglich speichern möchten, sollten Sie stattdessen erwägen, jede Datei in einer separaten Anfrage hochzuladen.

Um mehrere Dateien hochzuladen, hängen Sie sie einfach alle an das FormData-Objekt an. Wenn Sie ein Dateieingabefeld verwenden, können Sie eine Liste von Dateien abrufen, indem Sie dem Eingabefeld das Attribut multiple hinzufügen:

javascript
m.render(document.body, [
  m('input[type=file][multiple]', { onchange: upload }),
]);

function upload(e) {
  var files = e.target.files;

  var body = new FormData();
  for (var i = 0; i < files.length; i++) {
    body.append('file' + i, files[i]);
  }

  m.request({
    method: 'POST',
    url: '/api/v1/upload',
    body: body,
  });
}

Fortschritt überwachen ​

Manchmal ist es wünschenswert, dem Benutzer eine Fortschrittsanzeige anzuzeigen, um zu signalisieren, dass die Anwendung noch funktioniert, wenn eine Anfrage von Natur aus langsam ist (z. B. ein großer Datei-Upload).

m.request() legt sein zugrunde liegendes XMLHttpRequest-Objekt über den Parameter options.config offen, wodurch Sie Fortschrittsüberwacher (Fortschrittslistener) an das XMLHttpRequest-Objekt anhängen können:

javascript
var progress = 0;

m.mount(document.body, {
  view: function () {
    return [
      m('input[type=file]', { onchange: upload }),
      progress + '% completed',
    ];
  },
});

function upload(e) {
  var file = e.target.files[0];

  var body = new FormData();
  body.append('myfile', file);

  m.request({
    method: 'POST',
    url: '/api/v1/upload',
    body: body,
    config: function (xhr) {
      xhr.upload.addEventListener('progress', function (e) {
        progress = e.loaded / e.total;

        m.redraw(); // tell Mithril.js that data changed and a re-render is needed
      });
    },
  });
}

Im obigen Beispiel wird ein Dateieingabefeld gerendert. Wenn der Benutzer eine Datei auswählt, wird ein Upload initiiert und im config-Callback wird ein progress-Ereignishandler registriert. Dieser Ereignishandler wird ausgelöst, wenn es ein Fortschrittsupdate in der XMLHttpRequest gibt. Da das Fortschrittsereignis der XMLHttpRequest nicht direkt von der Virtual-DOM-Engine von Mithril.js verarbeitet wird, muss m.redraw() aufgerufen werden, um Mithril.js zu signalisieren, dass sich Daten geändert haben und eine Neudarstellung erforderlich ist.

Antwort in einen Typ umwandeln ​

Abhängig von der Gesamtarchitektur der Anwendung kann es wünschenswert sein, die Antwortdaten einer Anfrage in eine bestimmte Klasse oder einen bestimmten Typ zu transformieren (z. B. um Datumsfelder einheitlich zu parsen oder um Hilfsmethoden zu haben).

Sie können einen Konstruktor als Parameter options.type übergeben, und Mithril.js instanziiert ihn für jedes Objekt in der HTTP-Antwort.

javascript
function User(data) {
  this.name = data.firstName + ' ' + data.lastName;
}

m.request({
  method: 'GET',
  url: '/api/v1/users',
  type: User,
}).then(function (users) {
  console.log(users[0].name); // logs a name
});

Im obigen Beispiel wird davon ausgegangen, dass /api/v1/users ein Array von Objekten zurückgibt, der Konstruktor User für jedes Objekt im Array instanziiert wird (d. h. als new User(data) aufgerufen wird). Wenn die Antwort ein einzelnes Objekt zurückgibt, wird dieses Objekt als body-Argument verwendet.

Nicht-JSON-Antworten ​

Manchmal gibt ein Server-Endpunkt keine JSON-Antwort zurück: Beispielsweise fordern Sie möglicherweise eine HTML-Datei, eine SVG-Datei oder eine CSV-Datei an. Standardmäßig versucht Mithril.js, eine Antwort so zu parsen, als wäre sie JSON. Um dieses Verhalten zu überschreiben, definieren Sie eine benutzerdefinierte Funktion options.deserialize:

javascript
m.request({
  method: 'GET',
  url: '/files/icon.svg',
  deserialize: function (value) {
    return value;
  },
}).then(function (svg) {
  m.render(document.body, m.trust(svg));
});

Im obigen Beispiel ruft die Anfrage eine SVG-Datei ab, unternimmt nichts, um sie zu parsen (da deserialize lediglich den Wert unverändert zurückgibt), und rendert dann die SVG-Zeichenfolge als vertrauenswürdiges HTML.

Natürlich kann eine deserialize-Funktion auch aufwändiger sein:

javascript
m.request({
  method: 'GET',
  url: '/files/data.csv',
  deserialize: parseCSV,
}).then(function (data) {
  console.log(data);
});

function parseCSV(data) {
  // naive implementation for the sake of keeping example simple
  return data.split('\n').map(function (row) {
    return row.split(',');
  });
}

Abgesehen von der Tatsache, dass die obige parseCSV-Funktion nicht viele Fälle behandelt, die ein ordnungsgemäßer CSV-Parser behandeln würde, protokolliert der obige Code ein Array von Arrays.

Benutzerdefinierte Header können in dieser Hinsicht ebenfalls hilfreich sein. Wenn Sie beispielsweise eine SVG-Datei anfordern, möchten Sie wahrscheinlich den Inhaltstyp entsprechend festlegen. Um den Standard-JSON-Anfragetyp zu überschreiben, setzen Sie options.headers auf ein Objekt mit Schlüssel-Wert-Paaren, die den Namen und Werten der Anfrageheader entsprechen.

javascript
m.request({
  method: 'GET',
  url: '/files/image.svg',
  headers: {
    'Content-Type': 'image/svg+xml; charset=utf-8',
    Accept: 'image/svg, text/*',
  },
  deserialize: function (value) {
    return value;
  },
});

Abrufen von Antwortdetails ​

Standardmäßig versucht Mithril.js, xhr.responseText als JSON zu parsen und gibt das geparste Objekt zurück. Es kann nützlich sein, eine Serverantwort detaillierter zu untersuchen und manuell zu verarbeiten. Dies kann erreicht werden, indem eine benutzerdefinierte Funktion options.extract übergeben wird:

javascript
m.request({
  method: 'GET',
  url: '/api/v1/users',
  extract: function (xhr) {
    return { status: xhr.status, body: xhr.responseText };
  },
}).then(function (response) {
  console.log(response.status, response.body);
});

Der Parameter für options.extract ist das XMLHttpRequest-Objekt, sobald der Vorgang abgeschlossen ist, aber bevor es an die zurückgegebene Promise-Kette übergeben wurde, sodass das Promise immer noch in einem abgelehnten Zustand enden kann, wenn die Verarbeitung eine Ausnahme auslöst.

Ausgeben von Fetches an IP-Adressen ​

Aufgrund der (sehr simplen) Art und Weise, wie Parameter in URLs erkannt werden, werden IPv6-Adresssegmente als Pfadparameter-Interpolationen verwechselt, und da Pfadparameter etwas benötigen, um sie zu trennen, um korrekt interpoliert zu werden, führt dies zu einem Fehler.

javascript
// This doesn't work
m.request('http://[2001:db8::990a:cd27:4d9e:79]:8080/some/path', {
  // ...
});

Um dies zu umgehen, sollten Sie das IPv6-Adress- + Port-Paar stattdessen als Parameter übergeben.

javascript
m.request('http://:host/some/path', {
  params: { host: '[2001:db8::990a:cd27:4d9e:79]:8080' },
  // ...
});

Dies ist kein Problem bei IPv4-Adressen, und Sie können diese normal verwenden.

javascript
// This will work as you expect
m.request('http://192.0.2.15:8080/some/path', {
  // ...
});

Warum JSON anstelle von HTML ​

Viele serverseitige Frameworks bieten eine View-Engine, die Datenbankdaten in eine Vorlage interpoliert, bevor HTML bereitgestellt wird (beim Laden der Seite oder über AJAX), und verwenden dann jQuery, um Benutzerinteraktionen zu verarbeiten.

Im Gegensatz dazu ist Mithril.js ein Framework, das für Anwendungen mit umfangreicher Client-Logik entwickelt wurde, die in der Regel Vorlagen und Daten separat herunterladen und sie im Browser über JavaScript kombinieren. Die Verlagerung der Templating-Schwerarbeit in den Browser kann Vorteile bringen, wie z. B. die Reduzierung der Betriebskosten durch die Freigabe von Serverressourcen. Die Trennung von Vorlagen und Daten ermöglicht auch eine effektivere Zwischenspeicherung von Vorlagencode und ermöglicht eine bessere Wiederverwendbarkeit von Code über verschiedene Arten von Clients hinweg (z. B. Desktop, Mobil). Ein weiterer Vorteil ist, dass Mithril.js ein Retained-Mode-Paradigma für die UI-Entwicklung ermöglicht, das die Entwicklung und Wartung komplexer Benutzerinteraktionen erheblich vereinfacht.

Standardmäßig erwartet m.request, dass die Antwortdaten im JSON-Format vorliegen. In einer typischen Mithril.js-Anwendung werden diese JSON-Daten dann normalerweise von einer View konsumiert.

Sie sollten vermeiden, zu versuchen, serverseitig generiertes dynamisches HTML mit Mithril zu rendern. Wenn Sie eine vorhandene Anwendung haben, die ein serverseitiges Templating-System verwendet, und Sie diese neu strukturieren möchten, entscheiden Sie zunächst, ob der Aufwand überhaupt machbar ist. Die Migration von einer Thick-Server-Architektur zu einer Architektur mit umfangreicher Client-Logik ist in der Regel ein etwas großer Aufwand und beinhaltet die Refaktorierung von Logik aus Vorlagen in logische Datendienste (und die damit verbundenen Tests).

Datendienste können je nach Art der Anwendung auf viele verschiedene Arten organisiert werden. RESTful-Architekturen sind bei API-Anbietern beliebt, und Serviceorientierte Architekturen sind oft erforderlich, wenn es viele hochtransaktionale Workflows gibt.

Warum XHR anstelle von Fetch ​

fetch() ist eine neuere Web-API zum Abrufen von Ressourcen von Servern, ähnlich wie XMLHttpRequest.

Mithril.js' m.request verwendet XMLHttpRequest anstelle von fetch() aus einer Reihe von Gründen:

  • fetch ist noch nicht vollständig standardisiert und kann Spezifikationsänderungen unterliegen.
  • XMLHttpRequest-Aufrufe können abgebrochen werden, bevor sie aufgelöst werden (z. B. um Wettlaufsituationen in Instant-Search-UIs zu vermeiden).
  • XMLHttpRequest bietet Hooks für Fortschrittsüberwacher (Fortschrittslistener) für lang andauernde Anfragen (z. B. Datei-Uploads).
  • XMLHttpRequest wird von allen Browsern unterstützt, während fetch() nicht von Internet Explorer und älteren Android-Versionen (vor 5.0 Lollipop) unterstützt wird.

Derzeit erfordert fetch() aufgrund mangelnder Browserunterstützung in der Regel eine Standardvorlage (Polyfill), die unkomprimiert über 11 KB groß ist - fast dreimal größer als das XHR-Modul von Mithril.js.

Obwohl es viel kleiner ist, unterstützt das XHR-Modul von Mithril.js viele wichtige und nicht so trivial zu implementierende Funktionen wie URL-Interpolation und Serialisierung von Abfragezeichenketten (Querystring-Serialisierung) zusätzlich zu seiner Fähigkeit, sich nahtlos in das automatische Neuzeichnen-Subsystem von Mithril.js zu integrieren. Die fetch-Standardvorlage (Polyfill) unterstützt keine dieser Funktionen und erfordert zusätzliche Bibliotheken und Wiederholungscode (Boilerplates), um das gleiche Maß an Funktionalität zu erreichen.

Darüber hinaus ist das XHR-Modul von Mithril.js für JSON-basierte Endpunkte optimiert und macht diesen häufigsten Fall entsprechend prägnant - d. h. m.request(url) - während fetch einen zusätzlichen expliziten Schritt erfordert, um die Antwortdaten als JSON zu parsen: fetch(url).then(function(response) {return response.json()})

Die fetch()-API hat in einigen ungewöhnlichen Fällen einige technische Vorteile gegenüber XMLHttpRequest:

  • Sie bietet eine Streaming-API (im Sinne von "Video-Streaming", nicht im Sinne von reaktiver Programmierung), die eine bessere Latenz und einen besseren Speicherverbrauch für sehr große Antworten ermöglicht (auf Kosten der Codekomplexität).
  • Sie integriert sich in die Service Worker API, die eine zusätzliche Kontrollebene darüber bietet, wie und wann Netzwerkanfragen erfolgen. Diese API ermöglicht auch den Zugriff auf Push-Benachrichtigungen und Hintergrundsynchronisierungsfunktionen.

In typischen Szenarien bietet Streaming keine spürbaren Leistungsvorteile, da es im Allgemeinen nicht ratsam ist, überhaupt Megabyte an Daten herunterzuladen. Auch die Speichergewinne durch die wiederholte Wiederverwendung kleiner Puffer können ausgeglichen oder zunichte gemacht werden, wenn sie zu übermäßigen Browser-Repaints führen. Aus diesen Gründen wird die Wahl von fetch()-Streaming anstelle von m.request nur für extrem ressourcenintensive Anwendungen empfohlen.

Anti-Patterns vermeiden ​

Promises sind nicht die Antwortdaten ​

Die Methode m.request gibt ein Promise zurück, nicht die Antwortdaten selbst. Sie kann diese Daten nicht direkt zurückgeben, da eine HTTP-Anfrage lange dauern kann (aufgrund der Netzwerklatenz), und wenn JavaScript darauf warten würde, würde es die Anwendung einfrieren, bis die Daten verfügbar sind.

javascript
// VERMEIDEN SIE
var users = m.request('/api/v1/users');
console.log('list of users:', users);
// `users` ist KEINE Liste von Benutzern, sondern ein Promise

// ZIEHEN SIE VOR
m.request('/api/v1/users').then(function (users) {
  console.log('list of users:', users);
});
Pager
Vorherige Seiteroute(root, defaultRoute, routes)
Nächste SeiteparseQueryString(string)

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2024 Mithril Contributors

https://mithril.js.org/request.html

Veröffentlicht unter der MIT-Lizenz.

Copyright (c) 2024 Mithril Contributors