Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區最先提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了Promise
對象。ajax
ES6以前,JavaScript中異步編程分爲3類:DOM事件(如onclick)、網絡請求(如ajax)、定時器(setTimeout/setInterval)。他們均使用回調函數來進行異步調用。當回調函數中嵌套了回調函數,甚至是多層回調時,編碼就不夠直觀了。而使用Promise就能經過同步的編碼方式實現異步調用。編程
1.多層回調:使用setTimeout()函數執行3層嵌套的異步回調,編碼不直觀
promise
1 function async(){ 2 setTimeout(function(){ //回調函數1 3 console.log(1); 4 setTimeout(function(){ //回調函數2 5 console.log(2); 6 setTimeout(function(){ //回調函數2 7 console.log(3); 8 },1000); 9 },1000); 10 },1000) 11 } 12 13 async(); 14 15 //調用結果:1s後打印1 2s後打印2 3s後打印3
2.promise:以同步順序編碼來執行3次異步回調瀏覽器
經過return new Promise(),若是該promise中含有異步調用(setTimeout),則會等到異步調用中執行resolve()時纔會執行後面的then函數。網絡
1 new Promise(function(resolve,reject){ 2 //當即執行 3 console.log('new promise'); 4 setTimeout(() => { //回調函數1 5 console.log(11); //11 6 resolve(12); //返回value給下一個then函數 7 }, 1000); 8 }).then(function(value){ //回調函數2 9 //上一個promise resolve()後執行 10 console.log(value); //12 11 return new Promise(function(resolve,reject){ 12 setTimeout(() => { 13 console.log(21); //21 14 resolve(22); 15 }, 1000); 16 }); 17 }).then(function(value){ //回調函數3 18 //上一個promise resolve()後執行 19 console.log(value); //22 20 setTimeout(() => { 21 console.log(31); //31 22 }, 1000); 23 }); 24 25 //執行結果:當即打印new promise,1s後打印11/12,2s後打印21/22,3s後打印31
3.若是then的回調函數中沒有聲明式的return new Promise(); 那麼return會自動返回一個新的promise,因此也能夠鏈式執行then函數。異步
return自動返回的promise中並無異步操做(setTimeout沒有在promise中),因此後面的then函數是當即執行的。async
能夠參考MDN中關於then返回值的說明:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/then異步編程
1 new Promise(function(resolve,reject){ 2 //當即執行 3 console.log('new promise'); 4 setTimeout(() => { //回調函數1 5 console.log(11); //11 6 resolve(12); //返回value給下一個then函數 7 }, 1000); 8 }).then(function(value){ //回調函數2 9 //上一個promise resolve()後執行 10 console.log(value); //12 11 setTimeout(() => { 12 console.log(21); //21 13 }, 1000); 14 return 22; 15 }).then(function(value){ //回調函數3 16 //上一個promise resolve()後執行 17 console.log(value); //22 18 setTimeout(() => { 19 console.log(31); //31 20 }, 1000); 21 }); 22 23 //執行結果:當即打印new promise,1s後打印11/12/22,2s後打印21/31
4.異步編程原理:函數
JS是單線程指的是它的執行棧是單線程的(即JavaScript引擎的線程),稱爲主線程。JS 會建立一個相似於 while (true) 的循環,每執行一次循環體的過程稱之爲 Tick。每次 Tick 的過程就是查看任務隊列中是否有待處理任務(DOM事件/網絡請求/定時器的回調函數),若是有則取出相關回調函數放入執行棧中由主線程執行。編碼
異步操做會將相關回調添加到任務隊列中。而不一樣的異步操做添加到任務隊列的時機也不一樣,onclick 由瀏覽器內核的 DOM Binding 模塊來處理,當事件觸發的時候,回調函數會當即添加到任務隊列中。setTimeout 會由瀏覽器內核的 timer 模塊來進行延時處理,當時間到達的時候,纔會將回調函數添加到任務隊列中。ajax 則會由瀏覽器內核的 network 模塊來處理,在網絡請求完成返回以後,纔將回調添加到任務隊列中。
瀏覽器內核實現容許多個線程異步執行,在JavaScript引擎的線程外,還存在事件觸發進程、計時器觸發進程、http請求線程等,他們與JavaScript引擎的線程是互不影響的,不會形成阻塞。即JavaScript引擎的線程阻塞後,事件仍然會被觸發,但只是事件的回調函數沒法添加到任務隊列,或者沒法從任務隊列添加到執行棧中。
異步原理參考連接:https://blog.csdn.net/qdq2014/article/details/72383725/