最近被問到這個問題,jq的鏈式調用原理,當時比較懵=。=,畢竟如今jq接觸的機會變不多了。javascript
jq的鏈式調用其實就是好比咱們在選擇dom的時候,html
$('input[type="button"]') .eq(0).click(function() { alert('點擊我!'); }).end().eq(1) .click(function() { $('input[type="button"]:eq(0)').trigger('click'); }).end().eq(2) .toggle(function() { $('.aa').hide('slow'); }, function() { $('.aa').show('slow'); });
好比如上代碼,先選擇type類型爲button的全部DOM,而後再選擇第一個...java
咱們天然想到每次其實就是返回選擇後的結果,在js裏面有什麼東西能夠指代這個嗎?
若是你想到this就對了。promise
jq的方法都是掛在原型的,那麼若是咱們每次在內部方法返回this,也就是返回實例對象,那麼咱們就能夠繼續調用原型上的方法了,這樣的就節省代碼量,提升代碼的效率,代碼看起來更優雅。dom
可是也會出現一個問題:全部對象的方法返回的都是對象自己,也就是說沒有返回值,因此這種方法不必定在任何環境下都適合。ide
promise的鏈式調用如:函數
function start() { return new Promise((resolve, reject) => { resolve('start'); }); } start() .then(data => { // promise start console.log('result of start: ', data); return Promise.resolve(1); // p1 }) .then(data => { // promise p1 console.log('result of p1: ', data); return Promise.reject(2); // p2 }) .then(data => { // promise p2 console.log('result of p2: ', data); return Promise.resolve(3); // p3 }) .catch(ex => { // promise p3 console.log('ex: ', ex); return Promise.resolve(4); // p4 }) .then(data => { // promise p4 console.log('result of p4: ', data); });
Promise的then其實都是實現了 thenable 接口,每一個 then 都返回一個新的promise,除了第一個是start的實例其餘的已經不是一個promise了。this
reject的下面的then都會跳過(3d
更新,code
這裏其實說錯了,應該是then 裏面的回調被忽略執行,若是在這個then直接寫一個console.log()你發現仍是會打印,感謝jjc大佬特別指出這一點的錯誤,當 Promise 的狀態爲 rejected 時,這個回調函數沒有被執行,並非 then 函數沒有被執行。
eg:
Promise.reject(1).then(console.log('foo bar'));
依然輸出了 foo bar,可見 then 函數其實已經執行了。
若是寫成:
Promise.reject(1).then(() => console.log('foo bar'));
就不會輸出了。只是說,then 函數中傳入了一個回調函數,當 Promise 的狀態爲 rejected 時,這個回調函數沒有被執行,並非 then 函數沒有被執行。
作個合適的類比。如下 jQuery 鏈式調用:
$('#a_id_selector') .addClass('someclassname') .click(() => console.log('foo bar')) .prop('type', 'text');
運行這段代碼,也沒有輸出 foo bar,可是咱們不能說 click 函數被忽略掉了。只是裏面傳入的回調函數的條件沒有成立,這裏是點擊的條件,上面就是resolve的條件。
),只有catch纔會捕捉到。
promise的鏈式調用就和jq徹底不同了,promise鏈式調用的特色:
關於Promise的實現,我作了一個簡單的promise:
function easyPromise(fn) { var that = this; this.then = function (cb) { that.cb = cb; } this.resolve = function (data) { that.cb(data); } fn(this.resolve); } new easyPromise((resolve)=>{ setTimeout( ()=> { resolve("延遲執行"); },1000); }).then( (data) => { console.log(data); } )
能夠簡寫成
// 定義一個要傳給 promise 的函數,它接收一個函數(resolve)做爲參數。 // resolve 的做用是在合適的時間,通知 promise 應該要執行 then 裏面的回調函數了。 function promiseCallback (resolve) { setTimeout(() => { resolve("延時執行") }, 1000) } // 定義一個 要傳給 then 的回調函數 function thenCallback (data) { console.log(data) } // 實例化 promis,並分別傳入對應的回調 new easyPromise(promiseCallback) .then(thenCallback)
1.先經過 then 把 thenCallback 存起來
2.執行 promise 括號裏的函數,並把事先定義好的 resolve 函數做爲參數傳給他
fn(this.resolve)
3.執行 promiseCallback 咱們的邏輯就跳到 promiseCallback 函數內部去
setTimeout(() => { resolve("延時執行") }, 1000)
邏輯很簡單,就是等待1秒後,執行 resolve 函數, 這個 resolve 哪來的呢?
fn(this.resolve) -> promiseCallback (resolve) -> resolve
4.執行 resolve 咱們的邏輯就跳到 resolve 函數內部去
that.cb(data)
這個 that.cb 又是哪來的呢? 就是咱們第一步保存的 then括號裏面的回調函數,也就是 thenCallback
console.log(data)
因此就在1秒後輸出 延時執行
this是js函數運行過程當中的一個對象,環境對象。
誒,本身總結的發現仍是沒阮老師的好。。因此仍是看阮老師的吧,連接