В Java у нас есть "потоки", в CPython есть потоки (неконкурентные) и "процессы".
В JS, когда я начинаю async
функцию или метод, как я официально отношусь к этим "целям выполнения кода"?
Я слышал, что каждый такой блок кода выполняется от начала до конца *, а это означает, что в JS никогда не происходит одновременной обработки **. Я не совсем уверен, что это та же ситуация, что и в потоках CPython. Лично я не решаюсь использовать "поток" для того, что у нас есть в JS, поскольку эти "нити" настолько отличаются от параллельных потоков Java.
* Просто пояснить в свете Стивена Клири полезный ответ: я имею в виду "каждый такой синхронный блок кода". Очевидно, что если await
ожидание, управление будет выпущено...
** И, очевидно, никогда никакой "истинной параллельной" обработки. Я следую широко признанному различию между "параллельными" (только один поток в любой момент времени, но одна "цепочка выполнения" может уступить место другому) и "параллельно" (несколько процессов, реализующих истинную параллельную обработку, часто используя множественные Процессоры или ядра или процессы). Я понимаю, что эти "нити" в JS даже не параллельны: когда один метод AJAX или Promise
или метод/функция async
начинают выполняться, ничего не может произойти до тех пор, пока он не завершится (или await
произойдет)...
На сегодняшний день 24 человека, не более того, решили посмотреть на это.
FWIW, и если кто-нибудь из эксцентриков проявит интерес к этому вопросу в один прекрасный день, я предлагаю "веревки нитей" или просто "нити"... они свистят браузерный движок JS, он появится и просто не отпустит, если только они встретить await
.
Я разрабатываю это приложение, где три "нити" работают более или менее одновременно, все из которых связаны с вызовами AJAX и запросом базы данных... но на самом деле это очень предпочтительно, если 2-й из 3 выполняет и возвращает до 3-го.
Но поскольку 3-й запрос для MySQL намного проще, чем второй, прежний имеет тенденцию к возврату из своей "экскурсии" AJAX совсем немного раньше, если всем разрешено работать с неограниченной асинхронностью. Это приводит к большой задержке до того, как 2-ю нитку разрешено делать свои вещи. Чтобы заставить код выполнить и завершить вторую "нить", поэтому требуется довольно много принуждения, используя async
и await
.
Я прочитал один комментарий по асинхронности JS где-то, где кто-то предположил, что то, как все работает в JS, означает, что вам "никогда не придется беспокоиться о проблемах параллелизма и т.д.". Я не согласен: если вы на самом деле не знаете, когда await
будет разблокировано, это обязательно означает, что задействован параллелизм. Возможно, "свисающие нити" легче справляются, чем истинный "параллелизм", не говоря уже о истинном "параллелизме", однако...?
В JS, когда я начинаю асинхронную функцию или метод, как я официально отношусь к этим "целям выполнения кода"?
Из-за отсутствия лучшего термина я назвал их "асинхронными операциями".
Я слышал, что каждый такой блок кода выполняется от начала до конца
Это было верно... await
. Теперь есть несколько способов подумать об этом, оба из которых верны:
await
.await
разбивает свою функцию на несколько кодовых блоков, которые выполняют исключительно (каждый await
это "точка разделения").это означает, что в JS никогда не происходит параллельной обработки.
Я бы не согласился с этим утверждением. JavaScript усиливает асинхронность (до async
/await
, он использовал обратные вызовы или обещания), поэтому он имеет асинхронный параллелизм, хотя и не параллельный параллелизм.
Хорошая ментальная модель заключается в том, что JavaScript по сути является однопоточным, и один поток имеет очередь работы. await
не блокирует этот поток; он возвращается, и когда его thenable/Promise завершается, он планирует оставшуюся часть этого метода ("продолжение") в очередь.
Таким образом, вы можете одновременно выполнять несколько асинхронных методов. Именно так Node.js обрабатывает несколько одновременных запросов.
Мое понимание заключается в том, что эти "нити" в JS даже не параллельны: когда один метод AJAX или Promise или метод/функция async начинают выполняться, ничего не может произойти до тех пор, пока оно не закончится...
Нет, это неверно. await
вернет управление в основной поток, освободив его для выполнения другой работы.
то, как все работает в JS, означает, что вам "никогда не придется беспокоиться о проблемах параллелизма и т.д."
Ну... да и нет. Поскольку JavaScript по сути является однопоточным, никогда не возникает конкуренции над данными, разделяемыми между несколькими потоками (очевидно). Я бы сказал, о чем думал первоначальный писатель. Поэтому я бы сказал, что к северу от 90% проблем с синхронизацией потоков просто уйти.
Однако, как вы отметили, вам все равно нужно быть осторожным, изменяя общее состояние из нескольких асинхронных операций. Если они работают одновременно, то они могут выполняться в любом порядке, и ваша логика должна правильно обрабатывать это.
В идеале лучшим решением является переход к более функциональному мышлению, то есть избавление от общего состояния как можно больше. Асинхронные операции должны возвращать свои результаты вместо обновления общего состояния. Затем эти параллельные асинхронные операции могут быть составлены в асинхронном режиме более высокого уровня с использованием async
, await
и Promise.all
. Если это возможно, этот более функциональный подход к возврату, а не к состоянию и композиции функции сделает код более удобным для решения.
Но все же есть ситуации, когда это невозможно. Возможно разработать асинхронные эквиваленты классических синхронных координационных примитивов. Я разработал концептуальную концепцию AsyncLock, но не могу найти код где-нибудь. В любом случае, это возможно.
await
руки вернутся к двигателю JS, и позволит продолжить работу еще одной нити. Когда вы говорите «это неправильно», это неправильное понимание того, что я говорил: весь синхронный код в JS «перегружает» движок JS. Вот почему я говорю, что это даже не «одновременный» в истинном смысле: движок JS не может ничего делать, кроме как обрабатывать цепочку синхронного кода, пока эта цепочка не перестанет «зависать», возможно, из-за await
.
await
) ... что, на мой взгляд, таким образом квалифицируется как истинное совпадение. В отличие от JS. И именно поэтому вы можете иметь общее состояние в CPython, о котором вам нужно беспокоиться гораздо больше, чем в JS!