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