理解promise的三種姿勢
譯者按: 對於Promise,也許你會用了,卻並不理解;也許你理解了,卻只可意會不可言傳。這篇部落格將從3個簡單的視角理解Promise,應該對你有所幫助。
為了保證可讀性,本文采用意譯而非直譯,並且對原始碼進行了大量修改。另外,本文版權歸原作者所有,翻譯僅用於學習。
示例1中,asyncFunc()函式返回的是一個Promise例項:
// 示例1 function asyncFunc() { return new Promise(function(resolve, reject) { setTimeout(function() { resolve('Hello, Fundebug!'); }, 100); }); } asyncFunc() .then(function(x) { console.log(x); // 1秒之後列印"Hello, Fundebug!" });
1秒之後,Promise例項的狀態變為resolved,就會觸發then繫結的回撥函式,列印resolve值,即"Hello, Fundebug!"。
那麼,什麼是Promise呢?
- Promise呼叫是阻塞的
- Promise中儲存了非同步操作結果
- Promise是一個事件
Promise呼叫是阻塞的
示例2可以幫助我們理解阻塞:
// 示例2 function asyncFunc() { return new Promise(function(resolve, reject) { setTimeout(function() { resolve('Hello, Fundebug!'); }, 1000); }); } async function main() { const x = await asyncFunc(); // (A) console.log(x); // (B) 1秒之後列印"Hello, Fundebug!" } main();
以上程式碼是採用Async/Await語法寫的,與示例1完全等價。await的中文翻譯即為"等待",這裡可以"望文生義"。因此,相比於使用Promise實現,它更加直觀地展示了什麼是阻塞。
- (A)行: 等待asyncFunc()執行,直到它返回結果,並賦值給變數x
- (B)行: 列印x;
事實上,使用Promise實現時,也需要等待asyncFunc()執行,之後再呼叫then繫結的回撥函式。因此,呼叫Promise時,程式碼也是阻塞的。
Promise中儲存了非同步操作結果
如果某個函式返回Promise例項,則這個Promise最初相當於一個空白的容器,當函式執行結束時,其結果將會放進這個容器。示例3
// 示例3
function asyncFunc()
{
const blank = [];
setTimeout(function()
{
blank.push('Hello, Fundebug!');
}, 1000);
return blank;
}
const blank = asyncFunc();
console.log(blank); // 列印"[]"
setTimeout(function()
{
const x = blank[0]; // (A)
console.log(x); // 2秒之後列印"Hello, Fundebug!"
}, 2000);
開始時,blank為空陣列,1秒之後,"Hello, Fundebug!"被新增到陣列中,為了確保成功,我們需要在2秒之後從blank陣列中讀取結果。
對於Promise,我們不需要通過陣列或者其他變數來傳遞結果,then所繫結的回撥函式可以通過引數獲取函式執行的結果。
Promise是一個事件
示例4模擬了事件:
// 示例4
function asyncFunc()
{
const eventEmitter = {
success: []
};
setTimeout(function()
{
for (const handler of eventEmitter.success)
{
handler('Hello, Fundebug!');
}
}, 1000);
return eventEmitter;
}
asyncFunc()
.success.push(function(x)
{
console.log(x); // 1秒之後列印"Hello, Fundebug!"
});
呼叫asyncFunc()之後,sucesss陣列其實是空的,將回調函式push進陣列,相當於綁定了事件的回撥函式。1秒之後,setTimeout定時結束,則相當於事件觸發了,這時sucess陣列中已經註冊了回撥函式,於是列印"Hello, Fundebug!"。
當Promise成功resolve時,會觸發then所繫結的回撥函式,這其實就是事件。
參考
關於Fundebug
Fundebug專注於JavaScript、微信小程式、微信小遊戲、支付寶小程式、React Native、Node.js和Java實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了9億+錯誤事件,得到了Google、360、金山軟體、百姓網等眾多知名使用者的認可。歡迎免費試用!
版權宣告
轉載時請註明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/09/25/3-ways-to-understand-promise/