jQuery的鏈式調用原理,Promise的鏈式調用,this的問題

最近被問到這個問題,jq的鏈式調用原理,當時比較懵=。=,畢竟如今jq接觸的機會變不多了。javascript

jq的鏈式調用

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的鏈式調用

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

this是js函數運行過程當中的一個對象,環境對象。

誒,本身總結的發現仍是沒阮老師的好。。因此仍是看阮老師的吧,連接

相關文章
相關標籤/搜索