Будут ли вызовы асинхронных функций выполняться параллельно или последовательно
Что проверяют
Понимаете ли вы, что ожидание по умолчанию последовательно, и знаете ли, как запустить параллельно.
Как отвечать
По умолчанию последовательно. Ожидание приостанавливает выполнение до получения результата, поэтому следующий вызов начнётся только после завершения предыдущего.
let user = await api.user() // 1 секунда
let jobs = await api.jobs() // ещё 1 секунда
// итого 2 секунды, хотя запросы независимыЭто часто оказывается неожиданностью: код выглядит асинхронным, а работает последовательно. Асинхронность здесь означает, что поток не блокируется, а не что вызовы идут одновременно.
Чтобы выполнять параллельно, есть два способа.
Асинхронное связывание для фиксированного числа разнородных задач:
async let user = api.user()
async let jobs = api.jobs()
let (u, j) = try await (user, jobs) // обе стартовали сразу, ждём обеихЗадача начинается в момент объявления, а ожидание происходит позже. Итого примерно одна секунда вместо двух.
Группа задач для динамического числа однородных операций: задачи добавляются в цикле, результаты собираются по мере готовности.
Отдельно стоит назвать самую частую ошибку: цикл с ожиданием внутри.
for id in ids {
results.append(await api.fetch(id)) // строго по одному
}Сто запросов выполнятся друг за другом. Правильно использовать группу задач, причём с ограничением одновременности: запускать сразу тысячу запросов тоже плохо, это перегрузит и сеть, и сервер.
Полезное уточнение про порядок результатов: группа возвращает их по мере завершения, а не в порядке запуска. Если порядок важен, задача должна возвращать индекс вместе с результатом.
Где спотыкаются
Ждут параллельности от последовательных ожиданий.
Пишут цикл с ожиданием внутри и получают линейное время.
Запускают неограниченное число задач разом.
Рассчитывают, что результаты группы придут в порядке добавления.