The first `await` is waiting for the response-headers to arrive, so you know the status code and can decide what to do next. The second `await` is waiting for the full body to arrive (and get parsed as JSON).
It's designed that way to support doing things other than buffering the whole body; you might choose to stream it, close the connection early etc. But it comes at the cost of awkward double-awaiting for the common case (always load the whole body and then decide what happens next).
let r = await fetch(...);
if(!r.ok) ...
let len = response.headers.get("Content-Length");
if(!len || new Number(len) > 1000 * 1000)
throw new Error("Eek!");
Same thing. Maybe this doesn't make the double promise quite as visible, but it's still a double promise. You could probably replace the other await with a .then() too.
IMU because you don't necessarily want the response body. The first promise resolves after the headers are received, the .json() promise resolves only after the full body is received (and JSON.parse'd, but that's sync anyway).