Каковы различия между отсрочкой, обещаниями и фьючерсами?
Есть ли общепринятая теория за всеми этими тремя?
Каковы различия между отсрочкой, обещаниями и фьючерсами?
Есть ли общепринятая теория за всеми этими тремя?
Ответы:
В свете явной неприязни к тому, как я пытался ответить на вопрос ОП. Буквальный ответ: обещание - это что-то общее с другими объектами, а отложенное должно быть приватным. Прежде всего, отложенное (которое обычно расширяет Promise) может разрешиться само собой, в то время как обещание может быть не в состоянии это сделать.
Если вас интересуют подробности, изучите Promises / A + .
Насколько я знаю, главная цель - улучшить четкость и ослабить связь через стандартизированный интерфейс. Смотрите рекомендуемое чтение от @ jfriend00:
Вместо прямой передачи обратных вызовов функциям, что может привести к тесно связанным интерфейсам, использование обещаний позволяет разделить проблемы для кода, который является синхронным или асинхронным.
Лично я нашел deferred особенно полезным при работе, например, с шаблонами, которые заполняются асинхронными запросами, загрузкой скриптов с сетями зависимостей и предоставлением обратной связи с пользователем для формирования данных неблокирующим образом.
Действительно, сравните чистую форму обратного вызова, что-то делать после асинхронной загрузки 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.");
};
});
К формулировке обещаний (опять же извинения, я не в курсе 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.");
});
});
Извиняюсь за полупсевдокод, но я надеюсь, что это прояснит основную идею. По сути, возвращая стандартизированное обещание, вы можете обойти это обещание, тем самым обеспечивая более четкую группировку.
fn(callback, errback)
это не более тесно связано или менее полезно, чем fn().then(callback, errback)
- но в любом случае это неправильный способ использовать обещания. Я особенно ненавижу $.when
пример культа грузов - нет абсолютно никакой причины, по которой у вас не может быть $.when
функции, работающей с обратными вызовами.
Эти ответы, в том числе выбранного ответа, хороши для введения обещаний концептуально, но не хватает в особенности , что именно различие в терминологии , которая возникает при использовании библиотеки их реализации (и там есть существенные различия).
Поскольку это все еще развивающаяся спецификация , в настоящее время ответом является попытка изучить как ссылки (например, википедию ), так и реализации (например, jQuery ):
Отложено : никогда не описывается в популярных ссылках,
1 2 3 4,
но обычно используется реализациями как арбитр разрешения обещаний (реализации и ).
5 6 7
resolve
reject
Иногда deferreds также являются обещаниями (реализация then
),
5 6 в
других случаях считается более чистым иметь Deferred, способный только к разрешению, и принуждать пользователя к доступу к обещанию для использования .
7
then
обещание : наиболее всеобъемлющее слово для обсуждаемой стратегии.
Прокси-объект, хранящий результат целевой функции, синхронность которой мы бы хотели абстрагировать, плюс предоставление then
функции, принимающей другую целевую функцию и возвращающей новое обещание.
2
Пример из CommonJS :
> asyncComputeTheAnswerToEverything()
.then(addTwo)
.then(printResult);
44
Всегда описывается в популярных ссылках, хотя никогда не указывается, на кого ложится ответственность. 1 2 3 4
Всегда присутствует в популярных реализациях, и никогда не дает разрешения разрешения. 5 6 7
Будущее : кажущийся устаревшим термин, встречающийся в некоторых популярных ссылках 1 и, по крайней мере, в одной популярной реализации 8, но, по-видимому, постепенно исключаемый из обсуждения в пользу термина «обещание» 3 и не всегда упоминаемый в популярных введениях в тему. 9
Тем не менее, по крайней мере, одна библиотека использует термин в общем для абстрагирования синхронности и обработки ошибок, не предоставляя при этом then
функциональности.
10
Неясно, было ли намеренным избегать употребления термина «обещание», но, вероятно, это хороший выбор, поскольку обещания строятся вокруг «жизнеспособности».
2
Разница между обещаниями / А и обещаниями / А +
(TL; DR, Promises / A + в основном устраняет неясности в Promises / A)
Task
Что действительно заставило все это щелкнуть для меня, была эта презентация Домеником Дениколой.
В github он дал описание, которое мне нравится больше всего, оно очень лаконично:
Суть обещаний - вернуть нам функциональную композицию и всплывающие ошибки в асинхронном мире.
Другими словами, обещания - это способ, который позволяет нам писать асинхронный код, который почти так же легко написать, как если бы он был синхронным .
Рассмотрим этот пример с обещаниями:
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);
}
(Если это все еще кажется сложным, посмотрите эту презентацию!)
Что касается Deferred, это способ .resolve()
или .reject()
обещания. В спецификации Promises / B это называется .defer()
. В jQuery это так $.Deferred()
.
Обратите внимание, что, насколько мне известно, реализация Promise в jQuery не работает (см. Суть), по крайней мере, начиная с jQuery 1.8.2.
Предположительно, он реализует функции Promises / A thenables , но вы не получите правильной обработки ошибок, которую вы должны, в том смысле, что вся функциональность «асинхронная попытка / отлов» не будет работать. Что жаль, потому что иметь «try / catch» с асинхронным кодом - это круто.
Если вы собираетесь использовать Обещания (вы должны попробовать их со своим собственным кодом!), Используйте Q Криса Ковала . Версия jQuery - это просто агрегатор обратных вызовов для написания более чистого кода jQuery, но он упускает суть.
Что касается будущего, я понятия не имею, я не видел этого ни в одном API.
Изменить: выступление Доменика Дениколы на YouTube по обещаниям из комментария @Farm ниже.
Цитата из Майкла Джексона (да, Майкла Джексона ) из видео:
Я хочу, чтобы вы запомнили эту фразу: обещание - это асинхронная ценность .
Это превосходное описание: обещание похоже на переменную из будущего - первоклассную ссылку на то, что в какой-то момент будет (или произойдет).
Promise представляет собой прокси - сервер для значения не обязательно известен , когда создаются обещание. Это позволяет связывать обработчики с конечным значением успеха или причиной сбоя асинхронного действия. Это позволяет асинхронным методам возвращать значения, такие как синхронные методы: вместо конечного значения асинхронный метод возвращает обещание иметь значение в какой-то момент в будущем.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Этот deferred.promise()
метод позволяет асинхронной функции предотвращать вмешательство другого кода в ход выполнения или состояние его внутреннего запроса. Обещание предоставляет только отложенные методы, необходимые для присоединения дополнительных обработчиков или определения состояния ( затем выполнено, сбой, всегда конвейер, прогресс, состояние и обещание ), но не те, которые изменяют состояние ( разрешение, отклонение, уведомление, resolWith, отклонить и уведомить ).
Если цель указана, deferred.promise()
методы будут прикреплены к ней, а затем будут возвращать этот объект, а не создавать новый. Это может быть полезно для прикрепления поведения Promise к объекту, который уже существует.
Если вы создаете Отложенное, сохраните ссылку на Отложенное, чтобы в какой-то момент его можно было разрешить или отклонить. Возвращайте только объект Promise через deferred.promise (), чтобы другой код мог регистрировать обратные вызовы или проверять текущее состояние.
Просто мы можем сказать, что Обещание представляет значение, которое еще не известно, тогда как Отложенное представляет работу, которая еще не завершена.
promise
представляет значение, которое еще не известно deferred
представляет работу, которая еще не законченаОбещание является заполнителем для результата, который изначально неизвестен, а отложенный представляет вычисление, которое приводит к значению.
Ссылка