話題有點大,對於關注前端圈圈的朋友,這個話題也有點落入俗套,作爲森阿姨的第一篇掘金文,還但願能寫出一點新鮮感和小啓迪。森阿姨保證絕對原創。
咱們都知道,js的世界是單線程執行的,也就是說一個任務完成以後才能進行另外一個任務,這是由於js是運行在宿主進程多腳本語言,好比瀏覽器,好比node,宿主進程只會爲其分配一個js引擎線程。那麼對於耗時比較長的操做,若是繼續等,也許會很受傷,用戶體驗大打折扣,待在那裏啥也幹不了。因此,咱們須要一些方法來避免等待耗時多的操做,這就引出‘異步’了嗎,別急,引擎在沒有執行和將要執行的時候,怎麼知道這個操做的耗時長短呢?
要真正的理解一個機制,最好的方法是,咱們嘗試本身設計它。如今,停下來,咱們來本身想想,若是咱們開發瀏覽器引擎,咱們該怎麼作?
不少東西,咱們天天都在寫,瀏覽器引擎天天都在數以億計的機器上運行,看起來那麼天然,天然到咱們忘了去想這背後的道理和邏輯,而認爲這就是本該如此的,咱們甘之如飴地享受着前人給的一切,忘了咱們最初打開編輯器,敲下第一行代碼時候的夢想。
你生氣了,也許要問,若是是我,乾脆多線程多好,爲何不採起多線程執行js呢?大部分語言都是多線程的,好比c++,好比java,你也許在去茶水間洗杯子的時候,聽到後端的rd小哥哥在面試候選者的時候,老是要問怎麼解決的線程間通訊。但是,但是他們java啥的是面向不一樣的操做任務和數據的,而咱們寫的html,css以及js,根原本講是面向網頁的,說到底,是操做瀏覽器的dom元素的。而瀏覽器渲染dom元素,最怕的就是重繪與迴流,而多線程來操做dom,必然致使更高的複雜度,以及更高几率的重繪與迴流。
瀏覽器在解析的時候,已經把任務分了2類:同步任務、異步任務。js的單線程指的是同時只有一個js任務在運行,其餘的同步任務會被放到後面排隊等待,異步任務會被放到消息隊列中。瀏覽器自己並非單線程的,它還有EventLoop輪詢線程、UI渲染線程、網絡請求線程......等等其餘不少線程在作不一樣的任務。同步任務直接進入js解析線程排隊執行,異步任務會被執行線程掛起,進入消息隊列,經過回調函數來告知主線程本身的任務結束了,不用在等了,這樣主線程就會把這個任務也放到等待執行的隊列。咱們會在不少文章中看到‘執行棧’這個詞,這個詞森阿姨不想用,由於咱們都知道棧的特色是先進後出,而這個js的執行,是先來先服務。而‘執行棧’這個詞在這裏,表明的不是js任務,而是爲了這些任務的執行,分配的內存空間。計算機的好處就是誠懇,全部的一切都是這樣井井有理,不會向人類,沒有執行完,先喊一聲執行結束了,什麼插隊啊加塞啊,通通不存在的,全部的任務都按照預先設置好的規則層次分明的運行。
咱們的cpu速度遠遠高於網絡I/O傳輸的速度,在數據驅動以及mvvm普及的今天,大量的異步操做充斥在咱們代碼中,一個又一個的回調,讓咱們的代碼沒有設計感又難於複用和維護。
在es6中,promise終於被提了出來,成爲瀏覽器原生支持的方法,咱們認爲這本質也是一種語法糖,es6中不少東西均可以看做語法糖。沒有這顆糖,咱們的生活依舊能夠繼續,咱們能夠很快的寫出知足業務需求的邏輯和代碼,賺工資養家。但是,但是人生苦短,只有你甜,只有你甜。甜一點,有什麼很差呢,又有什麼好呢?咱們不得不學習各類新技術、看各類文章、接觸各類新名詞,不少前端老人苦不堪言,不少前端新手菜鳥彎道超車。
先說回調函數的缺點:1)回調地獄,繁瑣;2)代碼結構混亂,同步任務和異步任務堆疊交雜;3)與設計感無關,沒法使用先進的設計模式;4)全部的函數和邏輯經過回調實現,不方便其餘模塊複用;5)重複和冗餘。
promise能夠把異步過程串行起來寫,例如:css
new Promise(testFunction).then(function (result) {
}).catch(function (reason) {
}).then(function (result) {
}).catch(function (reason) {
}).then(function (result) {
}).catch(function (reason) {
});
複製代碼
從這段代碼中,咱們能夠看到異步操做就像同步操做同樣,也順序的被寫在一個個的.then以後,即便咱們不寫返回值,promise的每一步也都有一個默認的返回值,叫作:undefined。
promise是符合A+規範的,咱們也能夠本身實現promise,而且使用A+規範來測試它。
promise有3中狀態:pending(進行中)、resolved(解決)、rejected(失敗),這個promise翻譯成中文能夠叫作承諾,由於只要達到來解決或者拒絕,就不會再改變。它誠懇又有分寸,它終究不是人,它只是那麼單純。html