Это ошибка проектирования, основанная на наборе мнений и предположений. Он застрял, потому что он был запущен без полной технической проверки в процессе проектирования комитетом, который также столкнулся с противодействием многих поставщиков, внедряющих свои собственные уже с той же ошибкой, что затрудняет откат.
Как только стандарт для JS выходит в Интернет, его можно отозвать, даже если он нарушен, поскольку идея состоит в том, что веб-страницы не должны ломаться. Если кто-то написал страницу сегодня, а затем умер, ее можно будет просмотреть в вашем браузере через пять лет. Было бы очень проблематично, если бы при просмотре веб-страниц вы продолжали натыкаться на страницы, которые не работают с вашим браузером.
В очень простых случаях использования это не приносит большого вреда и устраняет путаницу в отношении того, может ли что-то быть асинхронным.
Для все более нетривиальных вариантов использования это причиняет все больше вреда и добавляет путаницы. Поначалу кажется, что проще рассуждать о вашем коде, но он жертвует менее тривиальным использованием ради наименее тривиального использования.
В целом намного проще рассуждать о вашем коде, если он не запускает вещи в следующем тике, которые вообще не должны быть асинхронными. Это случай выбора повреждения языка на втором уровне, чтобы обслуживать пользователей первого уровня, за счет пользователей второго уровня и выше, вместо того, чтобы работать над тем, чтобы помочь поднять пользователей первого уровня до пользователей второго уровня. Это снисходительное или пессимистическое дизайнерское решение.
Существует промежуточное решение, в котором можно запускать каждую задачу так, как будто она запускается после завершения текущего кода, но все запланировано в правильном порядке. Это не было реализовано, и это также спорно, поскольку компромиссы не всегда приводят к лучшим решениям. Этот компромисс приводит к проблемам с производительностью для стеков прямого возврата.
Способ работы promises означает, что стек прямых вызовов выполняется в глубину и выполняется до завершения (изолировано), а стек возвратных вызовов выполняется в ширину и выполняется по частям, чередующимся с другими стеками возвратных вызовов. Это два радикально разных понятия и поведения. Традиционно с обратными вызовами оба работают одинаково.
Это также означает, что вы не можете наивно заменить обратные вызовы обещаниями или чем-либо, основанным на обещаниях. Обратные вызовы дают вам больше возможностей, чем обещания. Если вы замените обратные вызовы обещаниями без учета этой разницы, вы можете создать код, который имеет проблемы со стабильностью и потенциальные проблемы с безопасностью, поскольку такое поведение неупорядоченных событий может привести к неожиданному переходу текущего потока кода.
Вы не можете полагаться на порядок, что означает, что есть случаи с обещаниями, когда, если вы просите много вещей, когда получаете их обратно, вам нужно дважды проверить, что это то, о чем вы просили, где вам не нужно было бы делать это с обратные вызовы. Вам также может понадобиться буферизовать и изменить порядок событий, что вам не нужно делать с обратными вызовами. Это также может сделать тесты ненадежными, если вы не постараетесь изолировать две выполняемые вещи.
Это также может создать серьезные проблемы с производительностью, которые не всегда легко предотвратить. Если вы используете промисы с сотней возвращенных результатов, возвращаемых сразу из одного события в итератор, каждый из которых занимает одну секунду на обратный вызов, а их глубина разрешения промисов равна двум, все они будут разбиты пополам с первыми половинами, которые все выполняются, а затем вторые половинки. Это означает, что потребуется 50,5 секунд, прежде чем что-либо сможет завершиться, тогда как с обратными вызовами через 50 секунд половина из них уже будет завершена. Если результат задачи передается другой внешней службе для обработки, она оставляет эту службу бездействующей в течение 50 секунд, когда она могла бы обрабатывать ваши результаты. Это делает обещания ужасными, когда вам нужна как низкая задержка, так и высокая пропускная способность для сервисов, которые берут на себя нагрузку, демонстрирующую слабость дизайна.
Невозможность наивно заменить обратные вызовы промисами — одно из самых разрушительных последствий этой ошибки проектирования, которая также перенесена в async/await. Если вы хотите преобразовать библиотеку обратного вызова, вы не можете просто изменить синтаксис, вы должны тщательно изучить семантику в каждой точке.
Планов по исправлению этого нет. Вы можете создавать свои собственные обещания, а генераторы могут использоваться для обеспечения того же синтаксиса, что и async/await, но с тем же предсказуемым и высокопроизводительным поведением обратных вызовов. Однако у вас могут возникнуть проблемы с другими библиотеками, которые все еще полагаются на собственные промисы.
person
jgmjgm
schedule
01.10.2019
$q.all()
, чтобы дождаться всех обещаний, а затем просто получить доступ к каждому значению в одной функции? - person Bergi   schedule 23.07.2014