即 setTimeout 自身就會先消耗一定的時間。
ok,那么說了半天Promise到底怎么和他們比較呢? 他的價值在哪里呢?
價值都在這里了!看下面的這個例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>testsettimeout</title> </head> <body> <div class="wrap"> </div> <script> let promise = new Promise(function(resolve, reject) { console.log('Promise! 我是Promise對象里的函數,我最早出現是因為我要給后面一個耗時的家伙提供數據a'); var a = 20; resolve(a); }); promise.then(function(value) { console.log('哈哈哈,我得到數據a了,要開始執行嘍。我是一個非常耗時的操作,依賴前面的數據,但是我想快一點執行,這有利于用戶體驗,所以別把我放在后頭啊;我被放在了一個新的線程上,不會阻塞別人的'); for (var i = 0; i < 1000000; i++) { var li = document.createElement("li"); document.querySelector(".wrap").appendChild(li); } console.log("執行完畢"); }); console.log('Hi! 我是什么都不依賴的程序,但我也想快一點執行,不能委屈我啊'); </script> </body> </html>
說明: 在已經執行過的情況下,錄制屏幕,然后按下刷新鍵,可以發現,在new Promise里的函數是立即執行的,緊接著是promise.then()之后的函數立即執行,而沒有等待then()函數,最后進入then()函數,說了一堆廢話,最后大約2 ~ 3s之后執行結束。故promise.then()函數才是真正的異步執行。
promise實現:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>promise</title> </head> <body> <script> function Mypromise(fn) { this.state = 'pending'; this.value = void 0; this.doneList = []; this.failList = []; // 在創建一個promise的時候,需要傳遞一個fn函數,接受參數resolve和reject。 // resolve和reject目前還沒有定義,因為用戶是直接調用的,如resolve('success'),所以這個resolve方法是需要我們自己來定義的。 var self = this; function resolve(value) { // 一旦resolve,狀態機的狀態由pending -> resolved // 并且在resolve的時候狀態必須是pending,才能轉換狀態。 // 異步執行所有回調函數 setTimeout(function () { if (self.state == 'pending') { self.state = 'resolved' self.value = value; // 一旦成功,我們就可以執行所有promise上掛載的 doneList 中所有的回調函數了,并將value值傳遞過去 for (var i = 0; i < self.doneList.length; i++) { self.doneList[i](value); } } }, 0); } function reject(reason) { // 一旦reject,狀態機的狀態由pending -> rejected // 在reject的時候狀態必須是pending,才能轉化狀態。 // 異步執行所有回調函數 setTimeout(function () { if (self.state == 'pending') { self.state = 'rejected' self.value = reason; // 一旦失敗,我么就可以把所有的 failList 調用了,并且傳遞 reason for (var i = 0; i < self.failList.length; i++) { self.failList[i](reason); } } }, 0); } fn(resolve, reject); } Mypromise.prototype = { constructor: Mypromise, // then方法接受成功時的回調和失敗時的回調 // 實際上,這里的then方法就像路由中的注冊路由一樣,是一個注冊的過程,而沒有真正的調用。 // 并且then是支持鏈式調用的,所以then應該返回一個promise。 如果返回舊的,那么因為狀態不能改變,所以沒有意義,所以我么一定要返回一個新的promise,這樣這個狀態機才可以再次正常的工作。 then: function (onResolved, onRejected) { var self = this; // 對于then而言,最終要返回一個新的promise,這樣才支持鏈式調用。 var promise2; // 這里要做一個判斷,看傳遞進來的是否是一個函數,如果是,則不變,如果不是,就拒絕。 // 如果是promise.then().then().then(function (value) {}); 我們還希望拿到value,那么就要把value在即使沒有用到onResolved的時候也傳遞下去。對于reason也是如此。 onResolved = typeof onResolved == 'function' ? onResolved : function (value) {return value;} onRejected = typeof onRejected == 'function' ? onRejected : function (reason) { return reason;} // 下面這一部分是比較核心的內容,因為then最終要返回一個promise,但是,這個promise究竟應該怎么返回呢? 如果在then中,用戶就返回了promise,那么我們就用戶的,如果用戶用的不是promise,那么我么就要自己封裝好這個promise了。 // 注意: promise也是需要異步調用的,所以可以使用promise進行封裝。 switch(this.state) { case 'resolved': // 如果resolved,則返回一個新的promise return promise2 = new Mypromise(function (resolve, reject) { setTimeout(function () { try { // 這里相當于直接就給執行了,看看返回的是什么值,如果是promise,那么直接就使用這個promise了。 var x = onResolved(self.value); if (x instanceof Mypromise) { x.then(resolve, reject); } } catch (e) { reject(e); } }, 0) }) case 'rejected': // 如果rejected,同樣也需要返回一個新的promise return promise2 = new Mypromise( function (resolve, reject) { setTimeout(function () { try { var x = onRejected(self.value); if (x instanceof Mypromise) { x.then(resolve, reject); } } catch (e) { reject(e); } }, 0); }) // 如果是pending狀態,我們就不能確定使用什么,等到狀態確定之后才能決定。 case 'pending': return promise2 = new Mypromise(function () { // 注意:一般then都是執行的這里, 即在then的時候進行注冊,把相應的成功的和失敗的都會初測在這里,push的是一個函數,所以這里的onResolved還是沒有執行的。 setTimeout(function () { self.doneList.push(function (value) { try { var x = onResolved(self.value) if (x instanceof Mypromise) { x.then(resolve, reject) } else { onResolved(value); } } catch (e) { reject(e) } }); console.log(self.doneList) self.failList.push(function (value) { try { var x = onRejected(self.data); if (x instanceof Mypromise) { x.then(resolve, reject); } } catch (e) { } }); }, 0); }) default: console.log(this.state); return; } }, catch: function (onRejected) { return this.then(null, onRejected); } } var promise = new Mypromise(function (resolve, reject) { if (5 > 3) { resolve('success'); } }); promise.then(function (value) { console.log('哈哈哈哈或'); }); </script> </body> </html>
總結
以上所述是小編給大家介紹的ES6中的promise,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com