Когда вы запускаете синхронную программу, она выполняется последовательно. Даже с условным ветвлением, циклами и вызовами функций ваш код будет работать шаг за шагом. Программа переходит к следующей операции только после завершения предыдущей.
Асинхронная программа ведёт себя иначе, хотя она и по-прежнему может выполнять только одну операцию в один момент времени. Ключевая разница заключается в том, что с асинхронностью система может не ждать завершения одного шага, а прерваться для выполнения другой операции, после чего вернуться, чтобы доделать первую. Когда мы пишем синхронный парсер, программа всегда ожидает, пока вернётся ответ от сервера, после этого совершает второй запрос и так далее до самого конца программы. Асинхронная версия вашей программы будет отправлять второй запрос к серверу в тот момент, когда сервер обрабатывает первый запрос. Именно за счёт этого достигается высокая производительность асинхронного кода.
Теперь, когда у вас есть базовое представление, предлагаю провести мысленный эксперимент, который позволит ещё лучше понять эту концепцию.
Итак, представьте себе, что в ваш день рождения родители решили сделать вам сюрприз и оставили дом в вашем распоряжении для вечеринки. Вы просыпаетесь утром, дома никого, и на столе лишь записка.
Сын/дочь, мы уехали на дачу. Веселись с друзьями, но никакого алкоголя и аморального поведения. Прежде чем пригласить своих друзей, сделай следующее:
Помой посуду в посудомоечной машине.
Постирай вещи в стиральной машине.
Достань мясо из морозилки и разморозь его.
Погуляй с собакой и проследи, чтобы она сделала все свои дела.
И не забудь сделать уроки.
Следи за младшим братом, чтобы с ним ничего не произошло.
Наверняка многим знакома следующая ситуация: есть много дел, каждое из которых по отдельности не требует много времени. Но этот мысленный эксперимент создан для того, чтобы поставить себя в странную ситуацию. Представьте, что вы живете в мире, где все происходит синхронно, шаг за шагом, как в синхронной программе.
У вас в руках список задач, которые необходимо выполнить во что бы то ни стало. Нет выполнения — нет вечеринки. В синхронном мире вы бы начали с первого пункта: загрузили бы грязную посуду в посудомоечную машину и стояли бы перед ней, пока не завершится её цикл работы. У вас достаточно медленная посудомоечная машина, и её цикл занимает от 60 до 80 минут. Когда вы прождали это время, наконец извлекли чистую посуду и поставили её на полку, в вашем списке осталось ещё 5 пунктов. Теперь вам нужно загрузить вещи в стиральную машину и подождать ещё от 15 до 90 минут, пока она закончит работу. К тому моменту, как вы закончили со стиркой, прошло уже не меньше двух часов.
Пока вы стояли столбом, ваш младший брат вместе с собакой перевернул сервант с маминым фарфором. Но реагировать вы не можете: у вас в списке ещё 4 задачи! Вместо того, чтобы собирать осколки фарфора и поднимать шкаф, вы достаёте из морозилки мясо и начинаете ждать, пока оно разморозится. В принципе, можно забыть про следующие пункты в списке, ведь мясо может размораживаться до самой ночи.
Допустим, мяса было немного, и оно разморозилось за несколько часов. Ваша собака к этому времени наложила большую кучу вместе с лужей где-нибудь на полу. К этому моменту вы со спокойной душой собираетесь гулять с собакой и ждёте, чтобы она сделала все свои дела. Но теперь это произойдёт не скоро, возможно, вообще только завтра. Да, у вас же есть младший брат! Всё это время он был без присмотра и совершил много шалостей, за которые вам достанется от родителей. Но вы же не могли следить за братом! Невозможно выполнить шестой пункт списка первым, иначе вы никогда не выполните все остальные. Как же хорошо жить в асинхронном мире, где мы можем выполнять поручения родителей в любом порядке и, например, включить стиральную машину и посудомоечную машину, а потом отправиться гулять с собакой и младшим братом.