Почему response.json( ) после fetch асинхронен?
Для чего так было сделано?
Все сделано логично и правильно. fetch() возвращает ответ как только все заголовки были прочитаны (не дожидаясь при этом получения полезной нагрузки). Если же надо получить и полезную нагрузку, то в ответе есть стрим, из которого уже читаете что Вам нужно (и сколько нужно).
Все остальные методы ( Response.json(), Response.text() и т.д ) являются просто хелперскими обертками над стримом и соответственно будут асинхронными.

Таким образом мы не делаем лишней работы и получаем тело ответа только в том случае, если оно нам действительно надо.
Мы ведь не посылаем никаких данных на сервер
По вашему получается, что асинхронной должна быть только передача и получение данных с сервера ))
Куча браузерного API работает асинхронно, используя промисы.
Конкретно про response.json( ). Ответ от сервера может быть весьма немаленьким и логично, что его чтение стоит сделать асинхронным. Но это моё предположение.