讓我們的承諾例子比較一個純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);
});
由於諾伯特·哈特爾指出,JSON.parse()來將掛起瀏覽器爲大型字符串。所以我用setTimeout()來延遲它的執行(在10毫秒的停頓之後)。這是Kris Kowal解決方案的一個例子。它允許當前的Javascript線程完成,在回調運行之前釋放瀏覽器以呈現DOM更改併爲用戶滾動頁面。
我希望commonjs promise框架也使用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回調的傳統向前傳球就相當於承諾漂亮多了。然而,經過兩次嘗試,我發現,在原始示例中參考代碼的整潔性,這些承諾是一個更加優雅的解決方案!
你是對的,使用承諾進行同步操作沒有意義。所以結果應該是平等的。但這是一個例子,並說明了諾言的使用。對於你的例子後運行的代碼確實有區別。如果您需要在示例之後運行某些內容(無需知道示例代碼的作用) – 2011-03-21 08:05:45