javascript語言的執行環境是單線程(single thread),就是指一次只能完成一件任務。若是有多個任務,就必須排隊,前面一個任務完成,再執行後面一個任務,以此類推。javascript
這種模式的好處是實現起來比較簡單,執行環境相對單純;可是隻要耗時比較多,假若有一個任務耗時很長,後面的任務都必須排隊等着,會拖延整個程序的執行。爲了解決這個問題,Javascript語言將任務的執行模式分紅兩種:同步(Synchronous)和異步(Asynchronous)。前端
Javascript處理異步的方法有如下幾種:vue
回調是一個函數被做爲一個參數傳遞到另外一個函數裏,在那個函數執行完後再執行。回調函數是異步編程最基本的方法,其優勢是簡單、容易理解和部署;缺點是容易產生回調地獄。java
ajax('XXX1', () => { // callback 函數體 ajax('XXX2', () => { // callback 函數體 ajax('XXX3', () => { // callback 函數體 }) }) })
這就是所謂的回調地獄,回調地獄帶來的負面做用有如下幾點:webpack
這種方式,異步任務的執行不取決於代碼的順序,而取決於某個事件是否發生。web
1.普通方式ajax
f1.on('done', f2);
上面這行代碼的意思是,當f1發生done事件,就執行f2。算法
2.onclick方法npm
element.onclick=function(){ //處理函數 } element.onclick=handler1; element.onclick=handler2; element.onclick=handler3; // 只有handler3會被添加執行
3.addEvenListener編程
elment.addEvenListener("click",handler1,false); elment.addEvenListener("click",handler2,false); elment.addEvenListener("click",handler3,false);
該方法的第三個參數是一個布爾值:當爲false時表示由裏向外,true表示由外向裏。
咱們假定,存在一個"信號中心",某個任務執行完成,就向信號中心"發佈"(publish)一個信號,其餘任務能夠向信號中心"訂閱"(subscribe)這個信號,從而知道何時本身能夠開始執行。這就叫作"發佈/訂閱模式"(publish-subscribe pattern)
首先,f2向信號中心jQuery訂閱done信號。
jQuery.subscribe('done', f2);
而後,f1進行以下改寫:
function f1() { setTimeout(function () { jQuery.publish('done'); }, 1000); }
f1執行完成後,向信號中心jQuery發佈done信號,從而引起f2的執行。f2完成執行後,能夠取消訂閱(unsubscribe)
jQuery.unsubscribe('done', f2);
這種方式的優勢:能夠經過查看「消息中心」,瞭解存在多少信號、每一個信號有多少訂閱者,從而監控程序的運行。
以上都是ES6以前的異步處理方式。ES6以後出現了promise。它是異步編程的一種解決方案,比傳統的解決方案(回調函數)——更合理和更強大。
Promise 對象有如下兩個特色。
1.對象的狀態不受外界影響。Promise 對象表明一個異步操做,有三種狀態:pending
(進行中)、fulfilled
(已成功)和rejected
(已失敗)。只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。
2.一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果
1.ES6 規定,Promise 對象是一個構造函數,用來生成 Promise 實例。
const promise = new Promise((resolve, reject) => { if (/* 異步操做成功 */){ resolve(success) } else { reject(error) } })
Promise接收一個函數做爲參數,函數裏有resolve和reject兩個參數:
resolve
方法的做用是將Promise
的pending
狀態變爲fullfilled
,在異步操做成功以後調用,能夠將異步返回的結果做爲參數傳遞出去。reject
方法的做用是將Promise
的pending
狀態變爲rejected
,在異步操做失敗以後調用,能夠將異步返回的結果做爲參數傳遞出去。2.Promise 實例生成之後,能夠用then
方法分別指定resolved
狀態和rejected
狀態的回調函數。
promise.then((success) => { // 對應於上面的resolve(success)方法 }, (error) => { // 對應於上面的reject(error)方法 } // 還能夠寫成這樣 (推薦使用這種寫法) promise.then((success) => { // 對應於上面的resolve(success)方法 }).catch((error) => { // 對應於上面的reject(error)方法 })
then(onfulfilled,onrejected)
方法中有兩個參數,兩個參數都是函數:
resolve()
方法(即異步成功後的回調方法)reject()
方法(即異步失敗後的回調方法)(第二個參數可選)。3.promise構造函數是同步執行的,then方法是異步執行的
const promise = new Promise((resolve, reject) => { console.log(1) resolve() console.log(2) }) promise.then(() => { console.log(3) }) console.log(4) // 1 2 4 3
Promise.finally()
用於指定無論 Promise 對象最後狀態如何,都會執行的操做。
promise .then(result => {···}) .catch(error => {···}) .finally(() => {···});
Promise.all()
用於處理多個異步處理,好比說一個頁面上須要等多個 ajax 的數據回來才執行相關邏輯。
const p = Promise.all([p1, p2, p3]);
p的狀態由p一、p二、p3決定,分紅兩種狀況。
Promse.race()
就是賽跑的意思,Promise.race([p1, p2, p3])裏面哪一個結果得到的快,就返回那個結果,無論結果自己是成功狀態仍是失敗狀態。
const p = Promise.race([p1, p2, p3])
上面代碼中,只要p一、p二、p3之中有一個實例率先改變狀態,p的狀態就跟着改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調函數。
async/await是JavaScript爲了解決異步問題而提出的一種解決方案,許多人將其稱爲異步的終極解決方案。async 函數,就是 Generator 函數的語法糖。
相較於 Generator,Async 函數的改進在於下面四點:
1.凡是在前面添加了async的函數在執行後都會自動返回一個Promise對象
async function test() { } let result = test() console.log(result) //即使代碼裏test函數什麼都沒返回,咱們依然打出了Promise對象
2.await必須在async函數裏使用,不能單獨使用
function test() { let result = await Promise.resolve('success') console.log(result) } test() //執行之後會報錯
總結移動端H5開發經常使用技巧(乾貨滿滿哦!)
從零開始構建一個webpack項目
總結幾個webpack打包優化的方法
總結前端性能優化的方法
總結vue知識體系之高級應用篇
總結vue知識體系之實用技巧
幾種常見的JS遞歸算法
封裝一個toast和dialog組件併發布到npm
一文讀盡前端路由、後端路由、單頁面應用、多頁面應用
淺談JavaScript的防抖與節流
關注的個人公衆號不按期分享前端知識,與您一塊兒進步!