Doch, schließlich gibt die Methode wieder einen Promise zurück.
Ok, da lag ich falsch, JSON.parse() wäre synchron. Aber so richtig asynchron wird Response.json() nicht sein.
Die Erklärung stimmt auch nur halb. Promises können synchron oder asynchron resolved werden, zum Beispiel kann man auch das synchrone JSON.parse() in eine Promise-API wrappen:
function json (jsonString) {
   return new Promise((resolve, reject) => {
      try {
         debugger;
         const jsonObject = JSON.parse(jsonString);
         resolve(jsonObject);
      } catch(e) {
         reject(e);
      }
   })
}
Ein Aufruf json('42') würde den String '42' synchron/blockierend parsen und sofort ein Promise zurück geben, das den Status resolved hat. An dem Breakpoint liegt der json-Aufruf also auf dem Callstack. Erst wenn man das Ergebnis mit then weiter vearbeitet, wird ein neuer Task in die Event-Queue gepusht.
Es gibt also bei Promise-APIs zwei Stellen an denen Asynchronität eine Rolle spielt:
- Der Übergang pending -> resolved(oderpending -> rejected) kann asynchron oder synchron sein.
- Die Ergebnisverwertung mit thenist immer asynchron.
Das kann man sich vermutlich am einfachsten vor Augen führen, indem man sich mit den DevTools die Callstacks zu kritischen Zeitpunkten ansieht. Hab' da mal was gebastelt: https://jsfiddle.net/6mxbz9Lh/2/.
 nicht angemeldet
 nicht angemeldet Gunnar Bittersmann
 Gunnar Bittersmann TS
 TS Matthias Apsel
 Matthias Apsel Orlok
 Orlok JürgenB
 JürgenB Rolf b
 Rolf b