理解Promise的3種姿勢


譯者按: 對於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所綁定的回調函數,這其實就是事件。

參考


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM