Комментарии 39
В Bluebird такой же конструктор Promise и есть поддержка работы с генераторами (если их поддержка есть в движке).
Ну и много клёвых фич. Конечно, Promises/A+.
Пользуюсь сам, советую другим.
«Обещания» глаза режет, вроде «промисы» уже вполне устоялось. Появление в хроме было небольшим шоком для меня. Месяц гадал, когда таки кто переведет статью, больно нужная штука в стандартной библиотеке :)
Полифил из статьи — штука хорошая, но не подменяет промисы 32го хрома (уже доступны и в стабильной ветке), а его реализация довольно серьезно отличается от текущей версии спецификации, запустите в нем тесты полифила — могут быть проблемы.
Возможно вы и правы по поводу переводу термина, я перед публикацией два раза правил по всему тексту Promise'ы — Обещания — Promise'ы — Обещания. А ведь можно ещё было и «промисы» в цикл включить)) На самом деле тонкий момент и угодить с переводом всем врятли получится… Меня почему то всегда тянет перевести термин на чистый русский, но к сожалению не всегда это получается… Я руководствовался переводом устоявшегося термина event'ы — события — «эвенты», чёт не помню что где либо встречал последний вариант.
Странно, что обычное русское слово «обещание» режет вам глаза. Мне уродливое «промисы» режет глаза куда больше.
Уговорили, начинаем пилить православное многозаполнение для Обещаний — благо сценарии Явы с русским сочетаются замечательно.
Скрытый текст
!function(Обещание){
  function функцияЛи(это){
    typeof это === 'function'
  }
  var есть      = Object.prototype.hasOwnProperty
    , уОбещания = есть.bind(Обещание);
  функцияЛи(Обещание)
  &&  'бросить,разрешить,отклонить,все,гонка'.split(',').every(уОбещания)
  &&  (function(разрешить){
        try {
          new Обещание(function(ы){ разрешить = ы }).затем(null);
          return функцияЛи(разрешить)
        } catch(ошибка){}
      })()
  ||  !function(){
        // Распрягайте, Хлопцы, Коней...
      }()
}(this.Обещание)

Странно, что Future'ы обозвали Promise'ами. Обычно под Promise понимается особый род Future, который может быть завершён юзерским кодом. Они нужны для создания собственных Future'ов или для написания комбинаторов над Future'ами. Но Promise'ы в JS такой фичи не имеют, ну или, по крайней мере, из статьи этого не видно.
Боюсь оказаться капитаном, но сразу на нативные методы я бы не стал кидаться) Уж лучше всегда иметь мало-мальскую обёртку над ними, чтобы при каком-либо изменении (ну или отсутствии реализации в браузере или её альтернативности) не пришлось перелопачивать весь код)
По крайней мере у нас в офисе этот прикол пошёл с того, что google translate «front-end developer» раньше как «разработчик переднего конца» переводил.
Никак не мог заставить себя юзать $.Deferred — оказывается, он и в самом деле кривой.
Он не кривой. Просто появился раньше, чем спека Promices/A+(*), поэтому реализует стандарт не совсем верно. Но менять реализацию никто не будет, т.к. уже полно кода написано с учетом старого API.

* $.Deffered реализует Promices/A
нестандартная реализация создает лишние сложности и сильно ограничивает кейсы их применимости (https://github.com/domenic/chai-as-promised/issues/1, например). поэтому — да, кривой. программисты с исторического факультета могут искать применение, но с практической точки зрения, чем раньше отправят в кунсткамеру это недоразумение, тем лучше — на сегодняшний день стандарт это реальность.
Я даже не представляю, как можно писать красивый и правильный код без деферредов/промисов…
Далеко не всегда стоят такие задачи, как в посте, особенно на фронтенде. Кроме того, я не то чтобы совсем не использовал $.Deferred — просто обходился по большей части без него, где это возможно.
Спасибо за перевод!

Generator'ы и Promise'ы очень похожи на async/await методы в C#.
Мир движется в правильном направлении, а то много вложенных callback'ов превращают код в макароны.
Читал статью и пытался сравнивать с async/await. Когда дошел до генераторов — аж подпрыгнул — вот оно, счастье!
Интересно… в будущем разработчики того же AngularJs откажутся от собственной реализации промисов в пользу написания обертки вокруг нативной реализации или оставят все как есть?
Я думаю многие совместимые либы обзаведутся версией, которая внутри содержит нативную реализацию. Причём определение требуемой версии (как и многие други вещи в JS) будет делаться в рантайме, по наличию/отсутствию объектов/фич.
Простите, я очень не в тему, наверное, но как поэтично звучит: «Конструктор обещаний».
:)
ОП, ты это серьезно: «когда ты ведёшь машину и одновременно говоришь по телефону»???
А смысл в нативной поддержке того, что и так легко реализуется на текущей версии языка? Я бы понял, если бы они перевели все апи на промисы, но такое половинчатое внедрение нафиг нужно. Тем более, что промисы уже устарели — в тренде реактивные вычисления). А генераторы — это конечно классно, но при использовании генераторов промисы и не нужны вовсе — они всего лишь эмулируют синхронные инструкции управления потоком (и то не все).

и удвоит объём кода приблизительно вдвое.


… а в военное время — до четырёх :)

Хорошая статья.
var promise = new Promise(function(resolve, reject) {
  // здесь вытворяй что угодно, если хочешь асинхронно, потом…
  
  if (/* ..если всё закончилось успехом */) {
    resolve("Работает!");
  }
  else {
    reject(Error("Сломалось"));
  }
});

//здесь вытворяй что угодно, если хочешь асинхронно, потом…
— если в том месте вызвать асинхронную функцию, а потом ваше условие, то это логически неправильно resolve должен вызываться в callbake асинхронной функции
Всё круто, но что делать, если нужно отменить запущенную цепочку действий (например, отменить загрузку статьи в примере http://www.html5rocks.com/en/tutorials/es6/promises/async-best-example.html)?
Promise.race в помощь. Нужно отменить — вызывайте cancel.

var cancel;
var promise = Promise.race([
  new Promise((_, reject) => cancel = reject),
  new Promise((resolve) => setTimeout(resolve, 1e4)),
]).then(
  () => { console.log('done') },
  () => { console.log('canceled') }
);
Очень смутно понимаю Ваш диалект JavaScript.

Создаётся 2 промиса: первый это полезное действие, а другой выполняется когда нужно отменить первый. Верно? Если да, то при отмене в фоне останется висеть выполняемая задача, что не очень хорошо.
Мой диалект JavaScript — актуальный стандарт — ECMAScript 6, если не в курсе, из которого здесь только стрелки и обещания, если понимаете смутно — пора подучить язык. Понимаете правильно. Может это, в некоторых случаях, не очень хорошо — но JavaScript к фоновой задаче доступа не имеет, что бы её прервать. А если имеет — прерывайте при отмене, какие проблемы? :)
Вообще, говоря, отменять что-то это не задача промисов. Промисы это как бы транспорт для возврата результата. А «отменяемость» это фича того поставщика данных, который нам даёт промис. Если реализовать это в промисе, то что делать с источниками данных, которые в принципе не поддерживают отмену?:

Promise.resolve(5) // возвращаем константу, отмена?

Поэтому в минимальной реализации промисов нету отмены. А вообще, если очень хочется, то можно.
Понятно, что отмена — это не задача промисов. Я имею ввиду, что это недостаток самого шаблона «обещания».
И всё-таки в прикладных задачах отмена нужна очень часто. С помощью цепочки обещаний команду для отмены можно было бы очень удобно с «хвоста» передать тому обещанию, которое в данный момент «в процессе».

«возвращаем константу, отмена?» — выполненные обещания не отменяются и не передают команду для отмены дальше.
выполненные обещания не отменяются и не передают команду для отмены дальше
Как раз такое поведение реализовано по второй ссылке что я скинул.
Cancel this promise with the given reason. The cancellation will propagate to farthest cancellable ancestor promise which is still pending.
А ещё можно создавать свой промис и пометить его как отменяемый.
Спасибо за ссылку. Вчера поизучал и начал внедрять. Отличный инструмент.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.