承諾的好處是它們在同步代碼和異步代碼之間做了一個簡單的比喻。爲了說明(使用Q庫):
同步:
var thisReturnsAValue = function() {
var result = mySynchronousFunction();
if(result) {
return getOneValue();
} else {
return getAnotherValue();
}
};
try {
var value = thisReturnsAValue();
console.log(value);
} catch(err) {
console.error(err);
}
異步:
var Q = require('q');
var thisReturnsAPromiseForAValue = function() {
return Q.Promise(function() {
return myAsynchronousFunction().then(function(result) {
if(result) {
// Even getOneValue() would work here, because a non-promise
// value is automatically cast to a pre-resolved promise
return getOneValueAsynchronously();
} else {
return getAnotherValueAsynchronously();
}
});
});
};
thisReturnsAPromiseForAValue().then(function(value) {
console.log(value);
}, function(err) {
console.error(err);
});
你只需要就習慣了,返回值總是作爲參數訪問到隨後的想法並且鏈接承諾等同於組成函數調用(f(g(h(x)))
)或按順序執行函數(var x2 = h(x); var x3 = g(x2);
)。這就是本質!當你引入分支時,事情會變得有點棘手,但你可以從這些基本原則中找出應該做的事情。因爲then-callbacks接受promise作爲返回值,所以可以通過返回另一個承諾來異步獲得一個值,這個異步操作可以解析爲基於舊值的新值,並且父承諾將不會解析,直到新的一個解決!而且,當然,您可以從if-else分支中返回這些承諾。
上面例子中說明的另一個非常好的事情是承諾(至少符合Promises/A +的承諾)以同樣類似的方式處理異常。第一個錯誤「引發」繞過了非錯誤回調,並跳出第一個可用的錯誤回調,很像try-catch塊。
對於它的價值,我認爲試圖用手工製作的Node.js風格的回調和async
庫來模仿這種行爲是它自己特殊的地獄:)。
遵循這些準則的代碼將成爲(假設所有的功能都是異步和返回的承諾):
beginTransaction().then(function() {
// beginTransaction() has run
return updateUsers(); // resolves the boolean value `updated`
}).then(function(updated) {
// updateUsers() has "returned" `updated`
if(updated) {
if(isBusiness) {
return updateBusiness().then(function(updated) {
if(!updated) {
return insertBusiness();
}
// It's okay if we don't return anything -- it will
// result in a promise which immediately resolves to
// `undefined`, which is a no-op, just like a missing
// else-branch
});
} else {
return deleteBusiness();
}
} else {
if(upsert) {
return insertUser().then(function() {
if(isBusiness) {
return insertBusiness();
}
});
}
}
}).then(function() {
return commitTransaction();
}).done(function() {
console.log('all done!');
}, function(err) {
console.error(err);
});
我認爲這是一個公平的問題。所有這些操作都被認爲是異步的嗎? – mooiamaduck
是的@mooiamaduck。其實我正在做數據庫插入/更新都是異步的。 – Eduardo
你有沒有看過'koa.js'(或'co',如果你沒有寫網絡應用程序)?如果你使用koa和承諾,它會看起來非常像你在那裏。或者,如果你想使用直接回調,你可以使用像async這樣的流量控制庫(例如,查看'async.auto'函數 – Kevin