摘要:作者珂珂滬江前端開發工程師本文為原創文章,有不當之處歡迎指出。只對未來發生的事情做出兩種基本情況的應對成功和失敗。在異步轉同步這條道路上,只是一個出彩的點,他還尚有一些缺陷和不足,并不是我們最終的解決方案。
作者:珂珂 (滬江前端開發工程師)
本文為原創文章,有不當之處歡迎指出。轉載請標明出處。
一個新事物的產生必然是有其歷史原因的。為了更好的以同步的方式寫異步的代碼,人們在JS上操碎了心。從Deferred到Promise到Generator再到Async和Await,各種工具的涌現就像是人類文明的進化史,從無到有,從簡陋到完善。
在這其中,Promise是較為重要的一個工具,也是后面不同工具進化完善的基石,今天我們就來了解一下:我們為什么需要Promise以及Promise為我們解決了什么問題。
我們需要什么? 1. 回調地獄我們應該都遇到過這樣的代碼:
callback嵌套函數層數少了還好,如果更多的話,大量的縮進會你的代碼慢慢地向屏幕右側移動。如果你寫了幾十層回調,那么你的代碼在一個屏幕的寬度上可能放不下了。這會讓我們的代碼變得難以維護,像一坨*。誠然我們可以通過其它的方式,把代碼抽出來平級對待,例如:
這么做雖然好看了,但: 1. 切斷了我們代碼結構上的層級串聯,而是采用了非結構的指向串聯 ,跳來跳去的函數引用,很可能就把我們繞暈了 2. 要耗費更多的時間來整理代碼
我們想要的是:既能串起來寫,又能少花時間。而Promise恰恰解決了這么一個痛點。
var promise = new Promise(...); promise.then(...) .then(...) .then(...) .then(...) .catch(...)
對!我們其實要的就是這樣一種“語法糖”。
2. 不讓回調里的return和throw變成擺設想想你在$.ajax()的success回調里寫個return xxx,沒啥用,return給誰?這種感覺就像打了一記空拳。另外,你如果在異步回調里throw一個錯誤,外面想接一下,比如你想這樣:
恭喜你!接不到,error被扔到全局環境里去了,BOOM!然后主線程就掛了。
Promise解決方案是什么?首先在字面意思上看Promise,翻譯成“承諾”的話有些抽象。那么具象一點,我們可以把Promise看成某種“合約”的管理者和執行者。
對,我們可以先把“他”想象成一個人,給他起一個簡短的名字,叫做:“P先生”。下面,就來看一下,“P先生”是如何幫助我們解決問題的(由于解決方案是“P先生”提供的,所以我們需要按照“他”的套路來)。
1. 定下合約首先,我們需要按照某個模板的樣子寫下一個“合約”,“合約”里告訴“P先生”的是將來可能發生的事情,“P先生”針對我們和“他”約定的事項,做不同的處理和反饋。Promise只對未來發生的事情做出兩種基本情況的應對:“成功” 和 “失敗”。
上述代碼中,首先我們召喚(new)了一個“P先生”,然后在回調函數里告訴了“他”具體的合約內容,合約規定:在setTimeout異步操作中,如果得到的秒數大于30s,則合約生效并且完成;否則的話,合約無效并且完成。“P先生”點點頭說:“好的,沒問題”。
注意:一旦做完resolve或者reject操作,合約的狀態就算定死了,沒辦法再改動了。
2. 合約完成后的操作上一步做完,“P先生”只會告訴我們合約完成的結果:成功 或 失敗。那么成功后該怎么做?失敗后該怎么做?我們還沒有告訴“P先生”,下面揮一揮小手(引用promise變量),把“P先生”招過來,繼續囑咐:
then給出了應對成功或失敗具體需要的方案,里面需要傳兩個處理函數
如果then中只傳遞了onRejected函數的話,那么相當于catch。
看到這里,我們發現Promise一定程度上幫我們解決了錯誤捕獲的問題。上述例子,我們在then鏈中產生的錯誤,最后都能被catch捕捉到(前提是你在最后面寫了catch)。
then里面的函數該寫點什么?每一個 promise 都會提供給你一個 then()函數。當我們的代碼跑在 then()函數內部時,是這樣子的:
在這個函數內部我們可以做什么呢?
也就是說我可以這么寫:
在上面的例子中看到,我們能在then中愉快的使用return和throw,并順利將值傳遞給下一層then或catch來處理。到這里Promise其實已經解決了之前我們說過的問題:“在異步回調里不能有效的使用return和throw”
總結看到這里,想必各位看官應該已經清楚的認識到Promise是個什么東西,并幫助我們解決了什么問題吧?當然,Promise API還提供了很多的方法,比如race, all,reject, resolve。本文的主要目的還是為了解釋Promise產生的原因和“他”解決了什么問題,至于API上的其它方法,相信在理解Promise的基礎上,會很容易就掌握的。
在異步“轉”同步這條道路上,Promise只是一個出彩的點,“他”還尚有一些缺陷和不足,并不是我們最終的解決方案。下一次,我們將一起學習新的工具:Generator!
參考資料:【翻譯】We have a problem with promises
JavaScript Promise迷你書(中文版)
ES6 JavaScript Promise的感性認知
Promise - JavaScript | MDN
iKcamp原創新書《移動Web前端高效開發實戰》已在亞馬遜、京東、當當開售。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/85121.html
摘要:三是控制反轉控制權在其他人的代碼上,假如異步函數是別人提供的庫,我們把回調函數傳進去,我們并不能知道異步函數在調用回調函數之外做了什么事情。錯誤捕捉相比回調函數的錯誤無法在外部捕捉的問題,能夠為一連串的異步調用提供錯誤處理。 前言 《JS異步編程之 callback》一文我們了解了JS 是基于單線程事件循環的概念構建的,回調函數不會立即執行,由事件輪詢去檢測事件是否執行完畢,當執行完有...
摘要:今天要介紹的是,就是回調函數與間的橋梁。什么樣的叫有兩個條件回調函數在主函數中的參數位置必須是最后一個回調函數參數中的第一個參數必須是。 作者:晃晃本文原創,轉載請注明作者及出處 Promise 自問世以來,得到了大量的應用,簡直是 javascript 中的神器。它很好地解決了異步方法的回調地獄、提供了我們在異步方法中使用 return 的能力,并將 callback 的調用納入了自...
摘要:如果過程中遇到引擎執行會被掛起線程,更新保存在一個隊列中等待引擎空閑才執行引擎線程負責解析運行執行時間過程會導致頁面渲染加載阻塞事件觸發線程,瀏覽器用以控制事件循環。 序 總所周知,javascript是一門依賴宿主環境的單線程的弱腳本語言,這意味著什么? javascript的運行環境一般都由宿主環境(如瀏覽器、Node、Ringo等)和執行環境(Javascript引擎V8,Ja...
摘要:瀏覽器與的異同,以及部分機制有人對部分迷惑,本身構造函數是同步的,是異步。瀏覽器的的已全部分析完成,過程中引用阮一峰博客,知乎,部分文章內容,侵刪。 瀏覽器與NodeJS的EventLoop異同,以及部分機制 PS:有人對promise部分迷惑,Promise本身構造函數是同步的,.then是異步。---- 2018/7/6 22:35修改 javascript 是一門單線程的腳本...
閱讀 1772·2021-10-11 10:59
閱讀 2415·2021-09-30 09:53
閱讀 1776·2021-09-22 15:28
閱讀 2804·2019-08-29 15:29
閱讀 1567·2019-08-29 13:53
閱讀 3214·2019-08-29 12:34
閱讀 2864·2019-08-26 10:16
閱讀 2672·2019-08-23 15:16