Pull to refresh

Comments 54

промисы как я понял уже считаются неэлегантными, на их место пришел async/await
Так что статья устарела.
На мой взгляд, эти новомодные абстракции безбожно текут, растворяя синтаксический сахар до несъедобного состояния.
Используйте Коллбэки, как завещали Керниган и Ричи. там по крайней мере понятно когда выполняется код.
там по крайней мере понятно когда выполняется код.

Можно подумать, что в промисах непонятно.

UFO just landed and posted this here
а async/await уже пришли?

Да уж давно. Не знаю, правда, как на счёт мелкомягких и мобильных.

UFO just landed and posted this here
async/await удобная штука, но только там где не придется писать часто .then в конечном потребителе. Браузеры не поддерживают асинхронные события. Получается везде придется все равно обрабатывать результат. Как по мне вся прелесть тает. Да и на ui редко много вложенных асинхронных вызовов. А вот если писать webserver на node.js, то там это как глоток воды в жару). На клиенте вместо promise лучше использовать rxjs. rxjs гибче и предоставляет много возможностей. Простой пример из жизни: SPA, пользователь зашел на route1, не дожидаясь результата запроса с сервера перешел на route2. rxjs позволяет отписаться от observable. При этом на отписку можно настроить abort http запроса
UFO just landed and posted this here
Я имею в виду следующее:
async function load(){}
window.addEventListener(«load», load, false);

а не писать каждый раз .then
UFO just landed and posted this here
async/await удобная штука, но только там где не придется писать часто .then в конечном потребителе.

Можете развернуть мысль?
Завершения любого Thenable можно ждать с помощью await.


Браузеры не поддерживают асинхронные события.

Простите, какие? Из тех, которые у меня стоят — только в 11 IE async/await не распознался.


Да и на ui редко много вложенных асинхронных вызовов.

Знаете, клиентская часть веб-приложения, это далеко не только ui. Вот, у меня тест-плеер. Вопросы подгружаются ajax-ом, и интерфейс проверки ответов тоже асинхронный. Без полноценного promise — никак. Мне пришлось свою обёртку над jQuary-вским deferred писать (требования совместимости с говном триллобита).

winform на c#, там можно писать вот такие штуки(пример из stackoverflow):
private async void button_Click(object sender, EventArgs e)
{
await LongOperation();
}
в js это будет так:
buttonEl.addEventListener(«click», buttonClick, false);
function buttonClick(e)
{
longOperation().then(......);
}
Было бы круто так, но это не поддерживают браузеры:
buttonEl.addEventListener(«click», buttonClick, false);
async function buttonClick(e)
{
await longOperation();
}
Было бы круто так, но это не поддерживают браузеры:

Реально не поддерживают? Какая ошибка возникает?


А если написать


buttonEl.addEventListener(«click», buttonClick, false);
function buttonClick(e)
{ 
return longOperation().then(......);
}

Тогда поддерживают?

Ничего, что async/await напрямую завязаны с работой с промисами? Ничего, что промисы решают огромную вложенность коллбеков (это не надуманная проблема, если что)? Ничего, что промисы более явно инкапсулируют значение, причем это значение можно гибко переиспользовать?


Ну да, х*й с ними с промисами, давайте не читать ничего и не думать, юзать коллбеки и сахар проще.

в чем проблема вложенности коллбэков? Рассматривайте их как конвейер

В том, что это трудно поддерживать. Если вложенность кода (не важно по какой причине — много if-веток, много вложенных функций, много коллбеков, циклов, whatever) — большая, то читать и понимать такой код гораздо проблематичнее. Любая flat сущность мозгом воспринимается в разы проще, чем иерархия.

А в чём проблема с промисами? Это те же самые коллбеки, только чуть по другому оформленные.

А я писал, что есть проблема с промисами?

А, точно, перепутал.

UFO just landed and posted this here

Кстати говоря, в некоторых случаях удобно комбинировать.
Вот, например, у меня есть функция handler, которая обрабатывает некоторые ошибки и возвращает для этих случаев валидный результат.


let result = await get('условный запрос').catch(handler);

Предполагается, что функция handler вернёт валидное значение в случае предусмотренных ошибок, и бросит без изменений непредусмотренные.

UFO just landed and posted this here
Вопрос к тем кто в теме: а есть ли какая то другая необходимость в использовании этого в браузере кроме как в случае блокировки микрофона и камеры? Что-то еще блокирует браузер? По логике ведь страницу надо блокировать и ждать пока нажмут.

Речь идет о фундаменте языка, а вы пишете про конкретные API (микрофон и камера). Связи не вижу от слова совсем. Тем более промисы ничего не блокируют.

UFO just landed and posted this here
промисы как я понял уже считаются неэлегантными, на их место пришел async/await

Вы не поверите, но под сахаром async/await находятся промисы.

Так что статья устарела

Нужно обладать колоссальным опытом что-бы подобное утверждать. На мой взгляд информация в статье актуальна и полезна.

Используйте Коллбэки, как завещали Керниган и Ричи. там по крайней мере понятно когда выполняется код.

Звучит как анти-совет. Промисы действительно решают проблему callback-hell.
Да и зачем вам знать когда выполняется код? — В голову приходит только тики для обновления мира, но обычно это в разработке игр используется.
а под промисами прячуться коллбэки
«callback hell»
callback hell в голове. Не надо использовать анонимные функции.

«Да и зачем вам знать когда выполняется код»

потому что это источник ошибок

Промисы решают не только вложенность (если вы про анонимные функции) — а еще массу полезностей, такие как создание переиспользуемого объекта с окончательным состоянием, большим количеством возможных "продолжений" (then-веток) и инкапсулирование значения. Все это на коллбеках конечно тоже реализовать можно, но… зачем, если это уже есть в промисах?


Прозрачность исполнения у промисов абсолютно такая же, как и у коллбеков. Ни промисы, ни коллбеки не затемняют вопрос "когда же исполнится мой код". Ответ очевиден — eventloop. Синхронные таски — здесь и сейчас, асинхронные — мы не знаем (если мы про результат этих тасков), так как эти веще делегируются на low-level API, который закрыт.

а под промисами прячуться коллбэки

Нет, промисы это новый функционал c новым Api.

потому что это источник ошибок

Приведите пример пожалуйста, не могу придумать сам.
Пример, в котором ошибку сложно/невозможно решить не зная время этой ошибки.
Я, например, использую trackjs в работе, этот сервис позволяет видеть все ошибки на фронте клиента, все до единой.
Нет, промисы это новый функционал c новым Api.

Может, вы даже полифил для них не писали?

Может, вы даже полифил для них не писали?
Нет, не писал, но использовал.

Можно узнать причем полифил к промисам?

Промисы — это новый функционал.
Полифилы — следствие graceful degradation подхода и нужны только там где используется этот подход.

В моем случае, например, сборщик сам определяет по целевым браузерам необходим ли полифил, и если необходим включит его сам из core-js.
Можно узнать причем полифил к промисам?

При том, промисы не содержат принципиальной новизны. Иначе бы полифил для них было написать невозможно.

При том, промисы не содержат принципиальной новизны
Не содержать принципиальной новизны? — Это классы не содержат принципиальной новизны и являются по факту сахаром, а промисы этот как раз новый функционал, которого никогда не было с новым низкоуровневым Api.

Промисы — это больше про асинхронное программирование и насколько мне известно, до 2014 года в стандарте его не было.

Иначе бы полифил для них было написать невозможно.

Разверните пожалуйста ответ — почему невозможно?

Зная язык программирования и алгоритм можно написать программу, которая повторяет низкоуровневый функционал данного языка программирования, правда у вас будут колоссальные потери в скорости и «ньюансы» работы.

Например, полифил промисов работает в 20 раз медленней чем родной.
Это классы не содержат принципиальной новизны

Для того, чтобы можно было реализовать классы, пришлось переделать процедуру создания объект, а кроме того, добавить возможность pзадать прототип не только создаваемого объекта, но и его конструктора.


Принципиальная новизна заключается в том, что классы позволяют создавать полностью работоспособных наследников от встроенных конструкторов. Например Array.
Полифил этого функционала невозможен.


Разверните пожалуйста ответ — почему невозможно?

А Вы ответ читать не пробовали? Для промисов возможно написать полностью работоспособный полифил. Следовательно, принципиальной новизны они не содержат. Это всего лишь перенос в стандартную библиотеку логики, которая могла бы быть реализована средствами самого языка.


Зная язык программирования и алгоритм можно написать программу, которая повторяет низкоуровневый функционал данного языка программирования, правда у вас будут колоссальные потери в скорости и «ньюансы» работы.

Ну, попробуйте создать наследника Array, так, чтобы Object.getPrototypeOf(MyArray) было равно Array.

Да, разумеется, это не заслуга классов. Наоборот, это то, без чего классы нельзя было бы сделать в нынешнем виде.
(Впрочем, мне порой не хватает фич, которые мы писали в своих реализациях).

Для того, чтобы можно было реализовать классы, пришлось переделать процедуру создания объект, а кроме того, добавить возможность pзадать прототип не только создаваемого объекта, но и его конструктора.
Да, я об этом и говорю, что class это сахар.

Принципиальная новизна заключается в том, что классы позволяют создавать полностью работоспособных наследников от встроенных конструкторов. Например Array.
Это не классы позволяют делать, а обновленный конструктор и новые методы в Object.

Полифил этого функционала невозможен.
Простите, но зачем полифил для конструктора Array, в каком-то браузере не работает [] или new Array? Я понимаю к чему вы ведете, но все таки… ощущение что вы хотите завалить меня нюансами языка а не найти в споре истину :)

А Вы ответ читать не пробовали? Для промисов возможно написать полностью работоспособный полифил. Следовательно, принципиальной новизны они не содержат. Это всего лишь перенос в стандартную библиотеку логики, которая могла бы быть реализована средствами самого языка.
Да, я прочитал, под развернуть я имел в виду пример.

Новизна != Возможность написания полифила.

Другими словами, возможно или нет реализовать полифил для нового функционала зависит от кол-ва нового функционала и его связью с другим новым/старым функционалом.
Например, для промисов нужен псевдо рантайм и генератор функций, поэтому полифил есть, но очень медленный.

Ну, попробуйте создать наследника Array, так, чтобы Object.getPrototypeOf(MyArray) было равно Array.
Мне кажется, что получится (чтобы они вернули true), но боюсь что-то точно перестанет работать либо статичные методы либо нативный конструктор либо еще что-то, они у вас не возвращают true только потому что у функции полифила и нативной функции конструктора разные id в рантайме.

но зачем полифил для конструктора Array, в каком-то браузере не работает [] или new Array?

Вы снова не читаете то, что я пишу. Полифил, позволяющий Вам отнаследоваться от Array, так чтобы это работало.


Новизна != Возможность написания полифила.

А утверждение-то было другое.


Новизна == Невозможность написание полифила.


для промисов нужен псевдо рантайм и генератор функций,

Неправда там тривиальный конструктор, оборачивающий переданную функцию. И тормозить там, по большому счёту, нечему.

Тот факт что это новое API не убирает коллбеки никуда. Или функции которые вы передаете аргументами в .then, .catch обработчики теперь имеют другое название?
Спасибо за перевод. Вопрос не по теме, но почему Вы в MDN перевод не добавите?
Добавлю, когда статья получит оценку профессионального сообщества и будет отредактирована с учетом замечаний и предложений коллег
Вот только
chooseToppings(function(toppings){
    placeOrder(toppings, function(order){
        collectOrder(order, function(pizza){
            eatPizza(pizza)
        }, failureCallback)
    }, failureCallback)
}, failureCallback)
«чуть-чуть» отличается от
chooseToppings()
.then(function(toppings){
    return placeOrder(toppings)
})
.then(function(order){
    return collectOrder(order)
})
.then(function(pizza){
    eatPizza(pizza)
})
.catch(failureCallback)
. В том смысле, что в первом случае мы можем по-разному реагировать на каждом уровне, а во втором случае обработчик один. Конечно, в него можно передавать тип исключения, но и данные для обработки всех вариантов исключений придется передавать все… Короче не хватает примера.
callback hell в головах:

chooseToppings(gotToppings, failureCallback)
function gotToppings(toppings) {
    placeOrder(toppings, gotOrder, failureCallback)  }
function gotOrder(order) {
     collectOrder(order, gotCollectedOrder, failureCallback)  }
function gotCollectedOrder(pizza) {
      eatPizza(pizza, failureCallback)        }
function failureCallback()     {console.log('Не шмогла...')}
Можно усложнить ситуацию). Что если необходимо дождаться завершения 2-3 параллельных запросов и только после обрабатывать результат

Тоже достаточно легко оборачивается. Вы потроха функции jQuery.when видели?

идея посмотреть, как на колбэках все это будет выглядить, насколько код будет лаконичен и приятен в сравнении с промисами, а не возможность ее решения)

Через счётчик. В каждом отдельном коллбеке — декремент счётчика и вызов общего коллбека, если счётчик достиг нуля. Но писать такое что-то не хочется.

Вы сами ответили, что писать элегантнее хочется), а значит промисы). А для ui посоветовал бы rxjs

А сколько потом приходится доплачивать программистам, чтобы они с поддержки подобного чуда не убежали через неделю?

"Обещания", "функции обратного вызова", "нам не нужна многослойность" — это ж всё приходится в голове сначала на английский переводить, чтобы понять, что вы имели в виду.


Тогда уж надо было идти до конца, и добавить методы обещаний "тогда", "лови" и "наконец-то".

"Обещания", "функции обратного вызова", "нам не нужна многослойность" — это ж всё приходится в голове сначала на английский переводить

Вы так говорите, как будто это трудно.


Тогда уж надо было идти до конца, и добавить методы обещаний "тогда", "лови" и "наконец-то".

Плохая аналогия — как котёнок с дверцей.

Мне не трудно, но теряется смысл перевода — он для людей, которые не знают английский.

Я не знаю английский. Мне тоже не трудно.

А где тут теряется смысл? Если кто-то не знает английского — то ему как раз "промис" будет абракадаброй, а как раз "обещание" — понятное без перевода русское слово.

Sign up to leave a comment.

Articles