Каковы различия между отложенным, обещанием и будущим в JavaScript?
в чем разница между отсрочками, обещаниями и фьючерсами?
Существует ли общепризнанная теория, стоящая за всеми этими тремя?
5 ответов
в свете очевидной неприязни к тому, как я попытался ответить на вопрос OP. Буквальный ответ: обещание-это что-то общее с другими объектами, в то время как отложенное должно быть закрытым. Прежде всего, отложенное (которое обычно расширяет обещание) может решить само себя, в то время как обещание может быть не в состоянии сделать это.
Если вы заинтересованы в мелочах, то изучите Обещания/A+.
насколько я понимаю, главная цель улучшите ясность и отпустите соединение через унифицированный интерфейс. См.рекомендуемая литература от @jfriend00:
вместо прямой передачи обратных вызовов функциям, что-то, что смогите привести к плотно Соединенным интерфейсам, используя обещания позволяет одному к отдельные проблемы для синхронного или асинхронного кода.
лично я нашел отложенный особенно полезным при работе с, например, шаблонами, которые заполняются асинхронные запросы, загрузка скриптов с сетями зависимостей и предоставление отзывов пользователей для формирования данных неблокирующим образом.
действительно, сравните чистую форму обратного вызова после загрузки 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.");
});
});
извиняюсь за полу-псевдо-код, но я надеюсь, что это делает основная идея-то понятна. В принципе, возвращая стандартизированное обещание, вы можете передать обещание, тем самым позволяя более четкую группировку.
эти ответы, включая выбранный ответ, хороши для введения обещаний концептуально, но не хватает конкретики того, в чем именно заключаются различия терминология, возникающая при использовании библиотек, реализующих их (и там are важные различия).
еще развивающаяся спецификация, ответ в настоящее время исходит из попытки исследовать обе ссылки (например,Википедия) и реализации (как jQuery):
-
отложить: никогда не описано в популярных ссылках, 1 2 3 4 но обычно используется реализациями в качестве арбитра разрешения обещания (implementing
resolve
иreject
). 5 6 7иногда deferreds также обещания (выполнение
then
), 5 6 в других случаях считается более чистым иметь отложенное только способный разрешения, и принуждать потребителя достигнуть посыла для используяthen
. 7 -
обещание: самое всеобъемлющее слово для обсуждаемой стратегии.
прокси-объект, хранящий результат целевой функции, синхронность мы хотели бы аннотация, плюс разоблачение принятие другой целевой функции и возвращение нового обещания. 2
пример CommonJS:
> asyncComputeTheAnswerToEverything() .then(addTwo) .then(printResult); 44
всегда описывается в популярных ссылках, хотя никогда не указывается, как на чью ответственность ложится решение. 1 2 3 4
всегда присутствует в популярных реализациях и никогда не дается разрешение abilites. 5 6 7
-
будущее: казалось бы, устаревший термин, найденный в некоторых популярных ссылках 1 и хотя бы одна популярная реализация, 8 но, по-видимому, постепенно из обсуждения в пользу срок 'обещание' 3 и не всегда упоминается в популярных введениях к теме. 9
однако, по крайней мере, одна библиотека использует термин в целом для абстрагирования синхронность и обработка ошибок, не предоставляя
then
функциональность. 10 Неясно, было ли намеренным избегать термина "обещание", но, вероятно, хороший выбор, так как обещания строятся вокруг 'thenables.' 2
ссылки
- Википедия о обещаниях и фьючерсах
- обещания / A+ spec
- стандарт DOM на обещаниях
- стандарт DOM обещает спецификацию WIP
- Dojo Toolkit Deferreds
- в jQuery Deferreds
- Q
- FutureJS
- функциональный раздел Javascript о обещаниях
- фьючерсы в интеграционном тестировании AngularJS
разное потенциально запутанные вещи
-
разница между обещаниями / A и обещаниями / a+
(TL; DR, Promises/A+ в основном разрешает двусмысленности в Обещания / А)
что действительно заставило все это щелкнуть для меня было презентации по Concha Denicola.
на github gist, он дал описание, которое мне нравится больше всего, это очень лаконично:
точки обещания вернуть нам функциональный состав и клокоча ошибки в асинхронный мир.
другими словами, обещания-это способ, который позволяет нам писать асинхронные код, который почти так же легко писать, как если бы это было синхронно.
рассмотрим этот пример, с обещаниями:
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()
обещания. В Обещания / B spec, это называется .defer()
. В jQuery, это $.Deferred()
.
обратите внимание, что как я знаю, реализация обещания в jQuery нарушена (см. эту суть), по крайней мере, с jQuery 1.8.2.
Он якобы реализует обещания/а thenables, но вы не получаете правильную обработку ошибок, в том смысле, что вся функциональность "async try/catch" не будет работать.
Что жаль, потому что иметь "try/catch" с асинхронным кодом совершенно круто.
если вы собираетесь использовать обещания (вы должны попробовать их со своим собственным кодом!), использовать Q Криса ковала. Версия jQuery - это просто некоторый агрегатор обратного вызова для написания более чистого кода jQuery, но упускает суть.
что касается будущего, я понятия не имею, я не видел этого ни в одном API.
Edit: youtube разговор Доминика Дениколы о обещаниях С @Farmкомментарий ниже.
цитата из Майкла Джексона (да, Майкл Джексон) из видео:
Я хочу, чтобы ты сожгла эту фразу в своем уме: обещание-это асинхронный стоимостью.
A обещание представляет прокси-сервер для значения, не обязательно известного при создании обещания. Это позволяет связать обработчики с конечным значением успеха или причиной сбоя асинхронного действия. Это позволяет асинхронным методам возвращать значения, такие как синхронные методы: вместо конечного значения асинхронный метод возвращает обещание иметь значение в какой-то момент будущее.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
на deferred.promise()
метод позволяет асинхронной функции предотвратить другой код от вмешательства в ход выполнения или состояние его внутреннего запроса. Обещание предоставляет только отложенные методы, необходимые для присоединения дополнительных обработчиков или определения состояния (тогда, сделано, терпеть неудачу, всегда, труба, прогресс, состояние и обещание), но не те, что изменить состояние (разрешить, отклонить, уведомить, resolveWith, rejectWith и notifyWith).
Если цель указана, deferred.promise()
присоединит к нему методы, а затем вернет этот объект, а не создаст новый. Это может быть полезно для присоединения поведения обещания к объекту, который уже существует.
Если вы создаете отложенный, сохраните ссылку на отложенный, чтобы он мог быть разрешен или отклонен в какой-то момент. Возврат только объекта Promise через отсроченный.promise (), чтобы другой код мог регистрировать обратные вызовы или проверять текущее состояние.
просто мы можем сказать, что a обещание представляет значение, которое еще не известно, где в качестве отложить представляет работу, которая еще не закончена.
- A
promise
представляет значение, которое еще не известно - A
deferred
представляет работу, которая еще не закончена
обещание-это результат, который изначально неизвестно, в то время как отложенный представляет вычисление, которое приводит к значению.
ссылка