Каковы различия между Отсрочкой, обещанием и Будущим в JavaScript?

Каковы различия между Отсрочками, Promises и фьючерсами?
Есть ли вообще одобренная теория за всеми этими тремя?

Ответы

Ответ 1

В свете очевидной неприязни к тому, как я попытался ответить на вопрос ОП. Буквальный ответ: обещание - это нечто разделяемое с другими объектами, в то время как отложенное должно быть закрытым. Прежде всего, отсрочка (которая обычно расширяет обещание) может разрешиться сама собой, в то время как обещание, возможно, не сможет этого сделать.

Если вы заинтересованы в мелочах, изучите Promises/A +.


Насколько мне известно, основной целью является улучшение ясности и ослабление связи через стандартизованный интерфейс. См. предлагаемое чтение от @jfriend00:

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

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

В самом деле, сравните чистую форму обратного вызова, когда-то делаете что-то после загрузки CodeMirror в режиме JS асинхронно (извинения, я не использовал jQuery в в то время как):

/* assume getScript has signature like: function (path, callback, context) 
   and listens to onload && onreadystatechange */
$(function () {
   getScript('path/to/CodeMirror', getJSMode);

   // onreadystate is not reliable for callback args.
   function getJSMode() {
       getScript('path/to/CodeMirror/mode/javascript/javascript.js', 
           ourAwesomeScript);
   };

   function ourAwesomeScript() {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   };
});

В promises сформулированную версию (опять же, извинения, я не в курсе jQuery):

/* Assume getScript returns a promise object */
$(function () {
   $.when(
       getScript('path/to/CodeMirror'),
       getScript('path/to/CodeMirror/mode/javascript/javascript.js')
   ).then(function () {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   });
});

Извинения за код полу-psuedo, но я надеюсь, что это делает ясную идею несколько ясной. В принципе, возвращая стандартное обещание, вы можете передать обещание, тем самым позволяя более четкую группировку.

Ответ 2

Эти ответы, включая выбранный ответ, хороши для введения promises концептуально, но не в деталях, каковы именно различия в терминология, возникающая при использовании библиотек, реализующих их (и там важные различия).

Поскольку все еще развивающаяся спецификация, в настоящее время ответ приходит к попытке просмотреть обе ссылки (например, wikipedia) и реализации (например, jQuery):

  • Отложенная: никогда не описываемая в популярных ссылках, 1 2 3 4 но обычно используется реализациями как арбитр обещания (реализация resolve и reject). 5 6 7

    Иногда отсрочка также promises (реализация then), 5 6 в других случаях он считался более чистым, чтобы иметь только Отсрочку способных разрешить, и заставить пользователя получить доступ к обещанию используя then. 7

  • Promise: наиболее всеобъемлющее слово для обсуждаемой стратегии.

    Объект-посредник, сохраняющий результат целевой функции, чья синхронность, которую мы хотели бы абстрагировать, а также разоблачение функции then принимая другую целевую функцию и возвращая новое обещание. 2

    Пример из CommonJS:

    > asyncComputeTheAnswerToEverything()
        .then(addTwo)
        .then(printResult);
    44
    

     

    Всегда описывается в популярных ссылках, хотя никогда не указывалось на решение которой возлагается ответственность. 1 2 3 4

    Всегда присутствует в популярных реализациях и никогда не дается разрешение. 5 6 7

  • Будущее: казалось бы, устаревший термин, найденный в некоторых популярных ссылках 1 и, по крайней мере, одна популярная реализация, 8 но, по-видимому, поэтапно отказался от обсуждения, предпочитая термин "Обещание" 3 и не всегда упоминается в популярных введениях к этой теме. 9

    Однако, по крайней мере, одна библиотека использует этот термин в общем случае для абстрагирования синхронизацию и обработку ошибок, не предоставляя then функциональность. 10 Неясно, было ли уклонение от термина "обещание" преднамеренным, но, вероятно, хороший выбор, поскольку promises построены вокруг "thenables". 2

Ссылки

Разные потенциально запутанные вещи

Ответ 3

Что действительно заставило все это щелкнуть меня, было эта презентация Доменик Деникола.

В github gist он дал описание, которое мне больше всего нравится, это очень краткий:

Точка promises заключается в том, чтобы вернуть нам функциональный состав и барботирование ошибок в асинхронном мире.

Другими словами, promises - это способ, который позволяет нам писать асинхронный код, который почти так же легко писать, как если бы он был синхронным.

Рассмотрим этот пример: promises:

getTweetsFor("domenic") // promise-returning async function
    .then(function (tweets) {
        var shortUrls = parseTweetsForUrls(tweets);
        var mostRecentShortUrl = shortUrls[0];
        return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning async function
    })
    .then(doHttpRequest) // promise-returning async function
    .then(
        function (responseBody) {
            console.log("Most recent link text:", responseBody);
        },
        function (error) {
            console.error("Error with the twitterverse:", error);
        }
    );

Он работает так, как будто вы пишете этот синхронный код:

try {
    var tweets = getTweetsFor("domenic"); // blocking
    var shortUrls = parseTweetsForUrls(tweets);
    var mostRecentShortUrl = shortUrls[0];
    var responseBody = doHttpRequest(expandUrlUsingTwitterApi(mostRecentShortUrl)); // blocking x 2
    console.log("Most recent link text:", responseBody);
} catch (error) {
    console.error("Error with the twitterverse: ", error);
}

(Если это все еще кажется сложным, смотрите эту презентацию!)

Относительно Отложенного, это способ .resolve() или .reject() promises. В Promises/B spec он называется .defer(). В jQuery он $.Deferred().

Обратите внимание, что, насколько мне известно, реализация Promise в jQuery нарушена (см. этот gist), по крайней мере, из jQuery 1.8.2.
Он предположительно реализует Promises/A thenables, но вы не получите правильную обработку ошибок, которую вы должны, в том смысле, что весь "async try/catch" не будет работать. Какая жалость, потому что наличие "try/catch" с асинхронным кодом совершенно круто.

Если вы собираетесь использовать promises (вы должны попробовать их со своим кодом!), используйте Kris Kowal Q. Версия jQuery - это всего лишь некоторый агрегатор обратного вызова для написания более чистого кода jQuery, но пропускает точку.

Что касается будущего, я понятия не имею, я не видел этого в любом API.

Изменить: Domenic Denicola youtube поговорить на Promises из @Farm ниже.

Цитата Майкла Джексона (да, Майкл Джексон) из видео:

Я хочу, чтобы вы сожгли эту фразу в своем уме: Обещание - это асинхронное значение.

Это отличное описание: обещание похоже на переменную из будущего - первоклассную ссылку на то, что в какой-то момент будет (или произойдет).

Ответ 4

A Promise представляет прокси для значения, которое не обязательно известно при создании обещания. Это позволяет связать обработчики с асинхронным действием в конечном итоге или с ошибкой. Это позволяет асинхронным методам возвращать такие значения, как синхронные методы: вместо конечного значения асинхронный метод возвращает обещание иметь значение в какой-то момент в будущем.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Метод deferred.promise() позволяет асинхронной функции предотвращать вмешательство другого кода в прогресс или состояние его внутреннего запроса. Promise предоставляет только методы Отложенные, необходимые для присоединения дополнительных обработчиков или определения состояния (, затем, done, fail, always, pipe, progress, state and prom), но не те, которые изменяют состояние ( разрешить, отклонить, уведомить, разрешить, сбросить, и notifyWith).

Если задана цель, deferred.promise() добавит на нее методы, а затем вернет этот объект, а не создаст новый. Это может быть полезно для привязки поведения Promise к уже существующему объекту.

Если вы создаете Отложенный, держите ссылку на Отложенную, чтобы ее можно было разрешить или отклонить в какой-то момент. Возвращайте только объект Promise через отложенный .promise(), поэтому другой код может регистрировать обратные вызовы или проверять текущее состояние.

Просто мы можем сказать, что Promise представляет значение, которое еще не известно, где Отложенная представляет работу, которая еще не завершена.


введите описание изображения здесь

Ответ 5

  • A promise представляет значение, которое еще не известно
  • A deferred представляет работу, которая еще не завершена.

Обещание - это заполнитель для результата, который изначально неизвестен, а отложенное представляет вычисление, которое приводит к значению.

Ссылка