這兩個是指兩個隊列,腳本總體代碼、setTimeout、setInterval、setImmediate、I/O、的回調及UI渲染都會被加入到 macrotask 隊列中, process.nextTick回調、Promise(瀏覽器實現)、MutationObserver回調都會被加入到microtask隊列。windows
Promise主要的功能是將異步執行結果保存起來,從而使得咱們再也不用回調的方式去處理異步任務的結果,咱們經過一個回調將異步任務的結果保存起來,在之後某個時刻經過各類姿式去使用它new romise(excutor).then(function(result)}).then(function(result){});的方式去執行異步任務,Promise 是經過回調來實現的,但它將回調統一,使得咱們不在去直接接觸回調,用看似有點像同步的方式去寫異步任務,也就僅僅是這樣而已,並無什麼新東西,這種同步方式只能說是相似同步,下一篇會講寫法更接近同步、更加有建術的 generator 。promise
function Promise(excutor) { var self = this; var status = 'PENDING'; //Promise的當前狀態 var data = undefined; //當前excutor(就是用戶的異步任務)的執行結果 self.onResolvedCallback = []; //excutor 執行成功後回調函數隊列 self.onRejectedCallback = []; //excutor 執行失敗後回調函數隊列 function resolve(value) { // TUDO 異步任務執行成功後的行爲 // 1 改變當前promise的status值 調用該方法 PENDING->RESOLVED // 2 執行onResolvedCallback隊列裏面的全部回調函數並傳遞異步任務的異步處理結果 // onResolvedCallback[i](data) } function reject(value) { // TUDO 異步任務執行失敗後的行爲 // 1 改變當前promise的status值 調用該方法 PENDING->REJECTED // 2 執行onRejectedCallback隊列裏面的全部回調函數並傳遞異步任務的異步處理結果 // onRejectedCallback[i](data) } excutor(resolve, reject); //執行用戶添加的任務 } Promise.prototype.then = function (onResolved, onRejected) { // onResolved異步任務執行成功的回調 // onRejected異步任務執行失敗後的回調 } 看起來就是這樣的 具體使用方式 new Promise(function(resolve,reject){ setTimeout(function(result){ // resolve(result) 或reject(result) 根據返回值決定 //這裏咱們確實仍是寫了回調,可是咱們在回調裏面沒有作太多的事件 //僅僅是傳遞了異步處理結果 想一想若是,咱們在這裏又要作依賴於result的 //異步任務會怎樣,回調地獄,代碼結構混亂,不容易讀 }); }).then(function(result){}) //這裏的result是從上面的那個回調裏面傳遞的,是同一個值
(1) resolve 函數和 reject 函數瀏覽器
function Promise(excutor) { var self = this; var status = 'PENDING'; //Promise的當前狀態 var data = undefined; //當前excutor(就是用戶的異步任務)的執行結果 self.onResolvedCallback = []; //excutor 執行成功後回調函數隊列 self.onRejectedCallback = []; //excutor 執行失敗後回調函數隊列 function resolve(value) { // TUDO 異步任務執行成功後的行爲 if(self.status === 'PENDING') { self.status = 'REJECTED'; // 改變當前promise的status值 調用該方法 PENDING->RESOLVED self.data = value; // 更新當前的data for(var i in self.onResolvedCallback) { self.onResolvedCallback[i](self.data); //執行onResolvedCallback隊列裏面的全部回調函數並傳遞異步任務的異步處理結果 } } } function reject(reson) { // TUDO 異步任務執行失敗後的行爲 if(self.status === 'PENDING') { self.status = 'REJECTED'; self.data = reson; for(var i in self.onRejectedCallback) { self.onRejectedCallback[i](self.data); } } } try { excutor(resolve.bind(this), reject.bind(this)); //執行用戶添加的任務 /*這裏爲何要經過經過 bind 來綁定上下文呢,主要是 resolve 依賴當 前 promise的內部屬性,在excutor函數體內,咱們是經過 resolve(data) 或者reject(reson) 的方式來調用經過這種方式調用 在非嚴格模式 resolve或reject的上下文是windows,在嚴格模式下是undefined*/ } catch(e) { reject.bind(this)(e); //出現異常則經過reject向後傳遞 } }
(2) then 方法的實現異步
then方法應當具有以下功能
(1) then方法必須返回一個Promise對象,也就是,對應用戶添加的邏輯要進行包裝
(2) 同一個對象可屢次調用then來添加邏輯,而且會按照添加順序執行函數
//例如: var promise = new Promise(function(resolve, reject) { //異步操做 而且在回調中調用了 resolve或者 reject將異步處理結果傳遞出去 }); promise.then(function(data){ //對異步結果data進行操做 }); promise.then(function(data){ //對異步結果data進行操做 }); //promise是同一個對象
(3) 能夠鏈式調用this
//例如: new Promise(function(resolve, reject){ //異步操做 而且在回調中調用了 resolve或者 reject將異步處理結果傳遞出去 }).then(function(data){}).then(function(data){});
這裏第一次和第二次調用then的對象是兩個不一樣的對象,這裏要注意prototype
[1] 若是第一個then的參數也是一個Promise那麼在第二個then的中會獲得第一個then的處理結果 [2] 若是第一個then的參數是一個函數而且有返回值,則在第二個then中會接收到這個返回值 [3] 其它狀況下都會獲得經過 new Promise(fn) 這裏這個異步fn的處理結果
(4) 咱們寫的Promise 要和全部符合Promise規範的 Promise 能協同工做(例如瀏覽器自帶的、第三方庫的)code
/** *@parms onResolved 任務成功時執行的回調 *@parms onRejected 任務失敗時執行的回調 */ Promise.prototype.then = function(onResolved, onRejected) { var self = this; var promiseThen; //then方法返回的promise //若是 onResolved或onRejected 不是函數咱們忽略它,而且添加一個用於傳遞異步結果得函數 onResolved = typeof onResolved ==='function' ? onResolved : function(value) {resolve(value);} onRejected = typeof onRejected ==='function' ? onRejected : function(reson) {resolve(reson);} /*若是在調用then添加依賴於異步處理結果的時候,異步任務已經執行完了,那麼 用異步的結果執行then裏面添加的任務*/ if(self.status === 'RESOLVED') { //這裏要將then裏面要添加的任務包裝成一個Promise,返回Promise 是爲了(3)中的鏈式調用 return promiseThen = new Promise(function(resolve, reject) { try { //執行then添加的任務 var x = onResolved(self.data); if(x instanceof Promise) { /*若是then添加的任務有返回值,而且返回值是Promise對象 則讓promiseThen去接受x的狀態和data值注意,這裏將 promiseThen的resolve,和reject做爲x的then參數傳入,這 樣當promiseThen的resolve和reject會在適當的時候被調用 從而使得promiseThen接受了x的狀態和data值Promise的不 同對象之間能實現相互影響,是經過將本身的resolve和 reject添加到其它對象中*/ x.then(resolve, reject); } else resolve(x); //若是x不是Promise使用x的值做爲promiseThen的結果 } catch (e) { reject(e); } }); } //和上面邏輯相同 if(self.status === 'REJECTED') { return promiseThen = new Promise(function(resolve, reject){ try { var x = onRejected(self.data); if(x instanceof Promise){ x.then(resolve, reject); } }catch(e) { reject(e); } }); } if(self.status === 'PENDING') { //當前Promise的異步任務沒有執行完,則將then裏面的異步任務 包裝後放入隊列 //包裝方法和上面同樣,區別是上面當即執行,這裏放入回調隊列。 return promiseThne = new Promise(function() { self.onResolvedCallback.push(function(){ try { var x = onResolved(self.data); if(x instanceof Promise) { x.then(resolve, reject); } catch(e) { reject(e); } } }); self.onRejectedCallback.push(function(){ try { var x = onRejected(self.data); if(x instanceof Promise) { x.then(resolve, reject); } catch(e) { reject(e); } } }); }); } }
寫到這裏Promise具體實現的 (1)、(2)、(3)的功能已經完成了,也就是若是不考慮與其它
的Promise交互那麼Promise的原理已經說清楚了,原本打算一篇文章寫完,可是篇幅太
長,因此打算分兩篇文章來寫,下一篇是generator,以後我會按照規範將(4)部分實現。server