Давайте сравним пример обещания чистого например Javascript:
// First we need a convenience function for W3C's fiddly XMLHttpRequest.
// It works a little differently from the promise framework. Instead of
// returning a promise to which we can attach a handler later with .then(),
// the function accepts the handler function as an argument named 'callback'.
function requestSomeDataAndCall(url, callback) {
var req = new XMLHttpRequest();
req.onreadystatechange = resHandler;
req.open("GET", url, false);
req.send();
function resHandler() {
if (this.readyState==4 && this.status==200) {
callback(this);
} else {
// todo: Handle error.
}
}
}
requestSomeDataAndCall("http://example.com/foo", function(res){
setTimeout(function(){
var data = JSON.parse(res.responseText);
setTimeout(function(){
var price = data.price;
setTimeout(function(){
print("The price is "+price);
},10);
},10);
},10);
});
Как Norbert Hartl отметил, JSON.parse() будет висеть браузер для больших строк. Поэтому я использовал setTimeout() для задержки его выполнения (после паузы в 10 миллисекунд). Это один из примеров решения Криса Коваля. Он позволяет завершить текущий поток Javascript, освободив браузер, чтобы представить изменения DOM и прокрутить страницу для пользователя до того, как будет выполнен обратный вызов.
Я надеюсь, что рамки обещаний commonjs также используют нечто вроде setTimeout, иначе более поздние обещания в примере статьи действительно будут выполняться синхронно, как опасались.
Моя альтернативная версия выглядит довольно уродливой, а последующие процессы требуют дальнейшего углубления. Я перестроил код, так что мы можем обеспечить нашу цепочку процессов в одном уровне:
function makeResolver(chain) {
function climbChain(input) {
var fn = chain.shift(); // This particular implementation
setTimeout(function(){ // alters the chain array.
var output = fn(input);
if (chain.length>0) {
climbChain(output);
}
},10);
}
return climbChain;
}
var processChain = [
function(response){
return JSON.parse(response.body);
},
function(data){
return data.price; // get the price
},
function(price){
print("The price is " + price);
}
];
var climber = makeResolver(promiseChain);
requestSomeDataAndCall("http://example.com/foo", climber);
Я надеялся, чтобы продемонстрировать, что традиционный вперед обгон обратных вызовов в Javascript довольно много эквивалентны обещания. Однако после двух попыток, которые, как я показал, со ссылкой на аккуратность кода в исходном примере, обещает гораздо более элегантное решение!
Вы правы, нет смысла использовать обещания для синхронных операций. Таким образом, результат должен быть равен. Но тогда это пример и иллюстрирует использование обещания. Для кода, который работает после вашего примера, действительно есть разница. Если вам нужно запустить что-то после примера, чем вы можете это сделать (используя обещающий подход), не зная ничего о том, что делает код примера –