亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

有關Promises異步問題詳解

2024-05-06 16:25:04
字體:
來源:轉載
供稿:網友

這篇文章主要介紹了有關JavaScript Promises異步問題詳解的相關資料,需要的朋友可以參考下

迄今為止,可能每個JavaScript開發者和他們的祖母都聽說過Promises。如果你沒有,那么你即將會。promises的概念是由CommonJS小組的成員在 Promises/A規范 中提出來的。Promises被逐漸用作一種管理異步操作回調的方法,但出于它們的設計,它們遠比那個有用得多。事實上,由于它們的多種用法,有無數人告訴我——在我寫過一些關于promises的東西后——我“遺漏了promises的重點”。那么什么是promises的重點呢?

一點關于Promises的東西

在我開始promise的“重點”之前,我想我應該給你一點它們如何工作的內貌。一個promise是一個對象——根據Promise/A規范——只需要一個方法:then。then方法帶有三個參數:一個成功回調,一個失敗回調,和一個前進回調(規范沒有要求包括前進回調的實現,但是很多都實現了)。一個全新的promise對象從每個then的調用中返回。

一個promise可以是三種狀態之一:未完成的,完成的,或者失敗的。promise以未完成的狀態開始,如果成功它將會是完成態,如果失敗將會是失敗態。當一個promise移動到完成態,所有注冊到它的成功回調將被調用,而且會將成功的結果值傳給它。另外,任何注冊到promise的成功回調,將會在它已經完成以后立即被調用。

同樣的事情發生在promise移動到失敗態的時候,除了它調用的是失敗回調而不是成功回調。對包含前進特性的實現來說,promise在它離開未完成狀態以前的任何時刻,都可以更新它的progress。當progress被更新,所有的前進回調(progress callbacks)會被傳遞以progress的值,并被立即調用。前進回調被以不同于成功和失敗回調的方式處理;如果你在一個progress更新已經發生以后注冊了一個前進回調,新的前進回調只會在它被注冊以后被已更新的progress調用。

我們不會進一步深入promise狀態是如何管理的,因為那不在規范之內,而且每個實現都有差別。在后面的例子中,你將會看到它是如何完成的,但目前這就是所有你需要知道的。

處理回調

像前面提到的為異步操作處理回調,是promises的最基本和最普通的用途,讓我們將一個標準的回調與一個采用了promise的回調比較一下。

 

 
  1. // Normal callback usage 
  2. asyncOperation(function() { 
  3. // Here's your callback 
  4. }); 
  5. // Now `asyncOperation` returns a promise 
  6. asyncOperation().then(function(){ 
  7. // Here's your callback 
  8. }); 

我很懷疑只是看到這個例子的話是否有人會真的關心去使用promises??雌饋頉]有什么好處,除了“then”使得在異步操作完成之后的回調函數被調用這件事看起來更加明顯。但是即使是這個好處,我們現在有了更多的代碼(抽象應該使我們的代碼更短,不是嗎?)而且promise比標準回調稍微性能差一點。

但是,不要讓這阻礙到你。如果這就是promise可以做的最好的事,這篇文章就不會存在了

厄運的金字塔

 

 
  1. // Normal callback usage => PYRAMID OF DOOOOOOOOM 
  2. asyncOperation(function(data){ 
  3. // Do some processing with `data` 
  4. anotherAsync(function(data2){ 
  5. // Some more processing with `data2` 
  6. yetAnotherAsync(function(){ 
  7. // Yay we're finished! 
  8. }); 
  9. }); 
  10. }); 
  11. // Let's look at using promises 
  12. asyncOperation() 
  13. .then(function(data){ 
  14. // Do some processing with `data` 
  15. return anotherAsync(); 
  16. }) 
  17. .then(function(data2){ 
  18. // Some more processing with `data2` 
  19. return yetAnotherAsync(); 
  20. }) 
  21. .then(function(){ 
  22. // Yay we're finished! 
  23. }); 

正如你所見,promises的使用使得事情變扁平而且更可讀了。這能起作用是因為——像早先提到的——then返回了一個promise,所以你可以將then的調用不停的串連起來。由then返回的promise裝載了由調用返回的值。如果調用返回了一個promise(像這個例子中的情形一樣),then返回的 promise裝載了與你的回調返回的promise所裝載的相同值。這內容很多,因此我將幫助你一步一步的理解它

異步操作返回一個promise對象。因此我們在那個promise對象中調用then,并且傳給它一個回調函數;then也會返回一個promise。當異步操作結束,它將給promise裝上數據。然后(第一次)回調被調用,數據被作為參數傳遞進去。如果回調不含有返回值,then返回的promise將會立即不帶值組裝。如果回調返回的不是一個promise,那么then返回的 promise將會立即裝載那個數值。如果回調返回一個promise(像例子中的),那么then返回的 promise將等待直到我們回調返回的promise被完全裝載。一旦我們回調的 promise被裝載,它裝載的值(本例中就是data2)將會被提交給then的promise。然后then中的promise裝載了data2。等等。聽起來有點復雜,但事實上很簡單,如果我說的你不能理解,我非常抱歉。我猜我可能不是談論它的最佳人選。

用命名的回調替代

但顯然 promises 不是使這個結構扁平化的唯一方法。在寫了一篇提到promises解決了厄運的金字塔問題的帖子之后,有個人對該帖評論說……

我想promises有時是有用的,但是“嵌套”的回調的問題(圣誕樹綜合癥)可以僅用一個命名的函數作為一個參數替代匿名函數的方法平常的處理:

 

 
  1. asyncCall( param1, param2, HandlerCallback ); 
  2. function HandlerCallback(err, res){ 
  3. // do stuff 

它的例子只是給出了一層深的例子,但它仍是正確的。我們來擴展我前面的例子,使這個看起來容易些。

命名回調

 

 
  1. // Normal callback usage => PYRAMID OF DOOOOOOOOM 
  2. asyncOperation(handler1); 
  3. function handler1(data) { 
  4. // Do some processing with `data` 
  5. anotherAsync(handler2); 
  6. function handler2(data2) { 
  7. // Some more processing with `data2` 
  8. yetAnotherAsync(handler3); 
  9. function handler3() { 
  10. // Yay we're finished! 

看看上面的代碼!他們絕對是對的!它就是一個扁平的結構,但是這里有個問題同樣也存在于 我以前從來沒有注意過的老的回調例子中:依賴性和復用性。依賴性和復用性是相互關聯的可逆類型。一樣東西依賴的越少,那么它的復用性就越大。在以上的例子中,handler1依賴handler2,handler2依賴handler3.這就意味著handler1無論出于任何目的都不可在被用除非handler2也呈現出來。假如你不打算重用他們,那么給你的函數命名又有什么意義呢?

最糟糕的的是handler1都不關心在handler2里面發生了什么事情。它壓根就不需要handler2除了和它異步工作。因此,讓我們消除這些依賴性然后通過用promise使函數更具復用性。

鏈式回調

 

 
  1. asyncOperation().then(handler1).then(handler2).then(handler3); 
  2. function handler1(data) { 
  3. // Do some processing with `data` 
  4. return anotherAsync(); 
  5. function handler2(data2) { 
  6. // Some more processing with `data2` 
  7. return yetAnotherAsync(); 
  8. function handler3() { 
  9. // Yay we're finished! 

這樣看起來是不是好多了?假如另外的函數存在的話,現在handler1和handler2都互不相關了。想看看他們是否真的很棒呢?現在handler1可以被用在不需要handler2的情況下了。相反,handler1被操作以后,我們將可以用另一個handler。

復用函數

 

 
  1. asyncOperation().then(handler1).then(anotherHandler); 
  2. function handler1(data) { 
  3. // Do some processing with `data` 
  4. return anotherAsync(); 
  5. function anotherHandler(data2) { 
  6. // Do some really awesome stuff that you've never seen before. It'll impress you 

現在handler1已經從handler2脫離而且可以被用在了更多的情形中,特別是那些由handler2提供的功能而我們又不想用的。這就是復用性!評論家解決代碼易讀性的唯一方法就是通過消除縮進。我們不想消除縮進僅僅是為了縮進。多層次的縮進僅僅是某些事情錯誤的標志,問題不一定在它本身。他就像是由脫水引起的頭痛。真正的問題是脫水,不是頭痛。解決的方法是獲得水合物,而不是用一些止痛藥。

并行異步操作

在前面我提到的文章里,我將promises與events在處理異步操作方面做了比較。遺憾的是,按照那些曾提到過的人在評論里給的說法,我比較的不是很成功。我描述出了promises的力量,接著轉到events來描述它們的力量,就像在我的特別項目里用到的那樣。沒有比較和對比。一位評論者寫道(修改了一點語法錯誤):

我想用帖子中的例子是一個壞的對照。有篇論文證明了promises的值將會怎樣,如果按下虛構的“啟動服務器按鈕”,將不僅僅是啟動一個web服務器,還有一個數據庫服務器,當它們都在運行的時候只是更新了UI。

使用promise的.when方法將會使這種“多個異步操作”例子變得普通,然而響應多個異步事件需要一個并不普通的代碼量。

他完全正確。事實上我沒有比較那兩種情況。那篇文章的要點實際在于說明promises不是異步操作的唯一機制,而且在一些情況下,它們也不一定是最好的。在這個評論者指出的情況下,promises當然是最佳的解決辦法。我們來看看他說的是什么

jQuery 具有 一個名為when的方法 ,可以帶上任意數量的promise參數,并返回一個單一的promise。如果任何一個promise傳入失敗,when返回的promise也會失敗。如果所有的promises被裝載,那么每個值都將會按照promises被定義的順序傳遞給附加的回調。

以并行的方式執行無數的異步操作非常有用,然后只要在它們之中的每一個結束之后繼續執行回調。我們看一個簡單的例子。

jQuery.when

 

 
  1. // Each of these async functions return a promise 
  2. var promise1 = asyncOperation1(); 
  3. var promise2 = asyncOperation2(); 
  4. var promise3 = asyncOperation3(); 
  5. // The $ refers to jQuery 
  6. $.when(promise1, promise2, promise3).then( 
  7. function(value1, value2, value3){ 
  8. // Do something with each of the returned values 
  9. ); 

人們經常說這是 promises 帶來的最好的東西之一,也是 promises 的一部分重要的意義所在。我也認為這是個簡化了大量操作的好特性,但是這種 when 方法的機制 根本就沒有在任何 Promises 規范中提到,所以我不認為它是 Promises意義所在。有一個規范提到了 when 方法,但是和上面的完全不同。就我所知,jQuery 是唯一的實現了這種 when 方法的庫。其他的 promises 庫,例如 Q, Dojo, 和 when 依照 Promises/B spec 實現了 when 方法, 但是并沒有實現注釋者提及的 when 方法。但是,Q 庫有一個 all方法,when.js 也有一個 parallel方法,與上面的 jQuery.when 方法作用一樣,只是它們接受一個數組類型的參數,而不是任意數量的參數。

值的表示

Promise是處理以下場景的更好的方法:

"我想在這個數據庫中找一個用戶,但find方法是異步的。"

因此,這里我們有了一個不能立刻返回值的find方法。但最終它確實"返回"了一個數值(通過一個回調的方式),而你希望以某種方式處理那個數值?,F在,通過使用一個回調,你能定義一個繼續部分,或者說“一些將在以后時間里處理那個數值的代碼”

Promise改變了那種“嘿,這里是一些你會發現你用來處理返回數值的代碼”。它們是一些允許"find"方法說“嘿,我將忙著找你要找的信息,但與此同時你能繼續等著返回結果,而且你能同時以任何你希望的方式處理它,就像實際的東西!”

Promise代表了真實的數值。那就是陷阱。它們工作在你像處理實際東西一樣處理Promise的時候。Promise的JavaScript實現期待你給它傳遞一個回調函數,這只是一個“巧合”,它不是重要的事情。

我相信這真的就是promise的重點。為什么?讀一讀 Promise/A規范 的第一句“一個promise代表了一個操作的一次完成最終返回的數值。“使它有點明顯了,是不是?好吧,即使那就是重點,那也不能阻止我在后面本文中呈現其他人的見解。不管怎么說,我們再多談論這個思想一點。

結論

promise的重點是它代表一個操作返回的最終結果值,但使用它們的原因是使同步操作更好的并行。自從異步編程進入此場景,到處都是彈出的回調,以奇怪的方式遮住我們的代碼。Promise是一種改變其的方法。Promise允許我們以同步的方式寫代碼,同時給予我們代碼的異步執行。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩性生活视频| 91免费看视频.| 亚洲国产精品专区久久| 亚洲新中文字幕| 国产在线拍偷自揄拍精品| 大荫蒂欧美视频另类xxxx| 疯狂欧美牲乱大交777| 成人福利网站在线观看| 国产精品亚洲片夜色在线| 亚洲视频欧美视频| 日韩不卡中文字幕| 午夜精品一区二区三区av| 久久久久久国产精品三级玉女聊斋| 91老司机在线| 欧美小视频在线| 中文字幕亚洲情99在线| 欧美中文字幕视频在线观看| 久久久久久久久久国产精品| 九九热精品视频在线播放| 精品成人69xx.xyz| 久久视频这里只有精品| 欧美国产一区二区三区| 国产成人精品在线视频| 国产精品v片在线观看不卡| 亚洲欧美日韩精品久久亚洲区| 亚洲精品成人免费| 亚洲国产古装精品网站| 国产精品久久91| 亚洲男人第一网站| 国产一区二区三区欧美| 伦理中文字幕亚洲| 国产日韩精品在线| 国产视频欧美视频| 在线看日韩av| 日韩成人在线网站| 美女福利视频一区| 日韩电视剧在线观看免费网站| 992tv在线成人免费观看| 国产精品夫妻激情| 国产日韩在线播放| 亚洲自拍欧美另类| 国内偷自视频区视频综合| 亚洲精品99久久久久| 91极品女神在线| 日韩欧美亚洲国产一区| 欧美做受高潮1| 国产成人精品视频在线观看| 亚洲香蕉成视频在线观看| 欧美大片免费观看在线观看网站推荐| 国产精品99久久久久久人| 性日韩欧美在线视频| 2018日韩中文字幕| 国产成人综合精品| 日本在线精品视频| 亚洲成av人乱码色午夜| 亚洲精品v欧美精品v日韩精品| 国产精品69精品一区二区三区| 成人av在线网址| 国产精自产拍久久久久久蜜| 国产精品亚洲片夜色在线| 欧美在线亚洲在线| 日韩黄色在线免费观看| 日韩精品一区二区视频| 日本亚洲欧美成人| 91超碰caoporn97人人| 日韩欧美亚洲国产一区| 日韩一区二区三区在线播放| 欧美日本啪啪无遮挡网站| 日韩亚洲欧美成人| 久久亚洲成人精品| 久久天天躁狠狠躁夜夜躁2014| 在线看福利67194| 国产一区二区三区视频免费| 91九色单男在线观看| 久久久久久久999| 亚洲视频第一页| 欧美xxxx18国产| 国产精品成人一区二区| 91在线高清免费观看| 九九视频这里只有精品| 欧美xxxx18性欧美| 欧美日韩成人在线视频| 午夜精品久久17c| 亚洲福利在线观看| 亚洲美女动态图120秒| 国产精品久久久久av| 欧美性猛交xxxx乱大交3| 久久手机精品视频| 国产免费久久av| 精品国产一区二区三区久久| 国产精品久久久久久久久影视| 亚洲一区二区国产| 欧美另类极品videosbestfree| 国产精品白嫩初高中害羞小美女| 欧洲成人午夜免费大片| 亚洲xxxx妇黄裸体| 欧美日韩在线观看视频小说| 91亚洲精品一区二区| 激情亚洲一区二区三区四区| 亚洲女同性videos| 久久久在线视频| 久久久国产精品亚洲一区| 欧美电影在线免费观看网站| 亚洲字幕在线观看| 91久久精品日日躁夜夜躁国产| 中文字幕日韩欧美| 亚洲精品av在线| 国产ts人妖一区二区三区| 精品国产乱码久久久久久婷婷| 国产精品久久久久久网站| 在线日韩欧美视频| 亚洲精品乱码久久久久久按摩观| 亚洲人成网站999久久久综合| 日韩欧美国产网站| 日本亚洲欧美三级| 欧美在线观看网址综合| 中文字幕一精品亚洲无线一区| 亚洲无亚洲人成网站77777| 日本一区二三区好的精华液| 欧美黄色小视频| 97香蕉超级碰碰久久免费的优势| 亚洲丝袜av一区| 国产丝袜一区二区| 亚洲自拍另类欧美丝袜| 69av在线视频| 97久久久免费福利网址| 亚洲xxxxx电影| 久久久久久久久久国产精品| 国产成人精品日本亚洲专区61| 欧美一级淫片videoshd| 国产精品久久99久久| 97国产精品视频人人做人人爱| 欧美丝袜一区二区| 国产极品jizzhd欧美| 亚洲电影在线看| 欧美成人h版在线观看| 日韩精品免费在线观看| 亚洲精品午夜精品| 亚洲娇小xxxx欧美娇小| 97高清免费视频| 中文国产亚洲喷潮| www.欧美精品| 美日韩精品视频免费看| 欧美重口另类videos人妖| 色综合老司机第九色激情| 亚洲精品美女视频| 亚洲精品97久久| 国产成人亚洲综合| 日韩av一区二区在线观看| 在线看片第一页欧美| 在线成人中文字幕| 欧美裸身视频免费观看| 羞羞色国产精品| 日av在线播放中文不卡| 亚洲剧情一区二区| 日韩视频在线免费| 欧美日韩国产精品| 亚洲精品一区二区三区不| 97视频在线观看免费高清完整版在线观看| 亚洲男女自偷自拍图片另类| 欧美亚洲国产成人精品| 久久免费视频这里只有精品| 激情懂色av一区av二区av| 热久久这里只有精品|