Lassen Sie uns das Versprechen Beispiel zu einem reinen Javascript Beispiel vergleichen:
// 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);
});
Wie Norbert Hartl wies darauf hin, JSON.parse() wird der Browser für große Saiten hängen. Also habe ich setTimeout() verwendet, um die Ausführung zu verzögern (nach einer Pause von 10 Millisekunden). Dies ist ein Beispiel für Kris Kowals Lösung. Es erlaubt den aktuellen Javascript-Thread zu vervollständigen, den Browser freizugeben, um DOM-Änderungen anzuzeigen und die Seite für den Benutzer zu scrollen, bevor der Callback ausgeführt wird.
Ich hoffe, das commonjs-Versprechungs-Framework verwendet auch etwas wie setTimeout, sonst werden die späteren Versprechen im Beispiel des Artikels tatsächlich synchron wie befürchtet ablaufen.
Meine Alternative oben sieht ziemlich hässlich aus, mit den späteren Prozessen, die eine weitere Einrückung erfordern. Ich umstrukturiert den Code, so dass wir unsere Prozesskette alle in einer Ebene zur Verfügung stellen können:
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);
Ich hoffte, dass traditionelle vorausGang Rückrufe in Javascript zu demonstrieren ziemlich gleichwertig Versprechen ist. Nach zwei Versuchen, die ich in Bezug auf die Ordentlichkeit des Codes im ursprünglichen Beispiel gezeigt habe, sind diese Versprechen jedoch eine weitaus elegantere Lösung!
Sie Es hat keinen Sinn, Versprechungen für synchrone Operationen zu verwenden. Also sollte das Ergebnis gleich sein. Aber dann ist es ein Beispiel und illustriert die Verwendung des Versprechens. Für den Code, der nach Ihrem Beispiel ausgeführt wird, gibt es tatsächlich einen Unterschied. Wenn Sie etwas nach dem Beispiel ausführen müssen, können Sie es tun (indem Sie den Versprechungsansatz verwenden), ohne etwas darüber zu wissen, was der Beispielcode macht –