Ну во-первых, твой await x.json() при await - это тот-же then.
И тебе правильно сказали, что без await и без костылей - ты eventLoop не обыграешь.
Можно выбрасывать при await и потом ловить то, чем оказывается промис в итоге, можно юзать Promise.withResolvers, что в принципе тоже без await нереально.
Например (с withResolvers):
const { promise, resolve, reject } = Promise.withResolvers()
const getProducts = () => fetch('https://fakestoreapi.com/products')
try {
resolve(
(await getProducts()).json()
)
} catch (e) {
reject(e)
}
console.log(
await promise
)
Но тебе выше уже сказали, что такие операции без минимум использования оператора
await - нереально исполнить. Не хочешь then - будешь юзать await, не хочешь await - будешь юзать then. Либо создавай своё подобие промисов на костылях, через кастомные события или сигналы.
P.S.: Чтобы понять, почему нельзя сделать то, что хочешь ты - прочитай то что тебе выше написали, а перед/после прочитай
это.