Я думаю, что мне, наконец, удалось согнуть мой разум вокруг javascript/ES6 Promises, по большей части. Это было непросто! Но что-то меня озадачивает дизайном.Является ли javascript Promise API более запутанным, чем нужно?
Почему конструктор Promise выполняет обратный вызов? Учитывая, что обратный вызов вызывается сразу, не может ли вызывающий абонент просто выполнить этот код вместо этого, тем самым избегая одного ненужного уровня изгиба ума «не называй меня, я позвоню тебе»?
Вот что я думаю о прототипическом примере использования обещаний, скопированном с Jake Archibald's Javascript Promises tutorial http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promisifying-xmlhttprequest, с комментариями разделенными.
Это обещание на основе обертка для запроса XMLHttpRequest GET:
function get(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
resolve(req.response);
}
else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error("Network Error"));
};
req.send();
});
}
Для меня, приведенный выше код будет гораздо легче понять, если бы оно было переписано следующим образом, используя очень немного другого рода обещание что я воображал, имея конструктор без аргументов и разрешить/отклонить методы:
function get(url) {
var promise = new MyEasierToUnderstandPromise();
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
promise.resolve(req.response);
}
else {
promise.reject(Error(req.statusText));
}
};
req.onerror = function() {
promise.reject(Error("Network Error"));
};
req.send();
return promise;
}
MyEasierToUnderstandPromise не слишком сложно реализовать с точки зрения Promise. Сначала я попытался сделать его фактическим подклассом Promise, но по какой-то причине я не мог заставить его работать; так что вместо этого я реализовал его как простую функцию фабрики, которая возвращает обычный старый объект Promise с парой дополнительных функций прилагается, которые ведут себя как функции-члены:
function NewMyEasierToUnderstandPromise() {
var resolveVar;
var rejectVar;
var promise = new Promise(function(resolveParam, rejectParam) {
resolveVar = resolveParam;
rejectVar = rejectParam;
});
promise.resolve = resolveVar;
promise.reject = rejectVar;
return promise;
};
Итак, почему не Обещай предназначен как это? Я думаю, что если бы это было так, это помогло бы мне понять обещания намного быстрее. Держу пари, это сократило бы время обучения пополам.
Я знаю, что многие умные люди приложили руку к созданию API обещаний, и все, кажется, в целом счастливы и гордятся этим, поэтому мне интересно, о чем они думали.
ваших «easierToUnderstandPromise» подобен jQuery.Deferred в пути. С вашим дизайном возвращаемое обещание обязательно предоставляет методы разрешения/отклонения. Я где-то читал, почему это «плохо», но я не могу найти этот ресурс (прошло много лет с тех пор, как я его прочитал) –
Подробнее о [ES7 async/await] (https://jakearchibald.com/2014/ES7 Асинхр-функции /). –
Существует также отложенный шаблон, но [он устарел по уважительной причине] (http://stackoverflow.com/q/28687566/1048572) – Bergi