3行程式碼實現一個簡易版promise

noahlam發表於2018-05-27

前言

作為一個後端過來的同學,剛入門前端的時候,被js種種「反人類」的概念折騰的死去活來的. 其中一個印象比較深刻的,就是promise,感覺實在太難理解了...所有就有了寫個簡單的promise的想法. 希望能幫助到一些跟我一樣,感覺promise很難理解的新同學.

promise的教程網上多如牛毛,其中寫的比較通俗易懂的莫過於阮一峰的es6,反正我是他的書才懂的. 所以今天,我們也不會來複述一遍如何使用promise,今天我們從另一個角度學習promise, 先自己動手造一個輪子--實現一個最簡單的promise,解決 回撥地獄 的問題.

簡單實現

請看程式碼

function easyPromise (fn) {
    this.then = cb => this.cb = cb
    this.resolve = data => this.cb(data)
    fn(this.resolve)
}
複製程式碼

詳解

上面的程式碼就實現了一個簡單的,實現then回撥的「promise」,這裡為了縮短程式碼量,用了es6的簡寫,實際展開應該是這樣

function easyPromise (fn) {
    var that = this

    // 第一步,定義 then()
    this.then = function (cb) {
        //先將 then() 括號裡面的引數(回撥函式)儲存起來
        that.cb = cb
    }

    // 定義一個 resolve
    this.resolve = function(data) {
        that.cb(data)
    }

    // 將 resolve 作為回撥函式,傳給fn
    fn(this.resolve)
}
複製程式碼

接下來我們看看如何使用

new easyPromise((resolve) => {
    setTimeout(() => {
        resolve("延時執行")
    }, 1000)
}).then((data) => {
    console.log(data)
})
複製程式碼

結果: 控制檯在1秒之後,輸出 延時執行

同樣為了方便理解,我們不妨把以上程式碼寫好理解一點.

// 定義一個要傳給 promise 的函式,它接收一個函式(resolve)作為引數。
// resolve 的作用是在合適的時間,通知 promise 應該要執行 then 裡面的回撥函式了。
function promiseCallback (resolve) {
   setTimeout(() => {
      resolve("延時執行")
   }, 1000)
}

// 定義一個 要傳給 then 的回撥函式
function thenCallback (data) {
    console.log(data)
}

// 例項化 promis,並分別傳入對應的回撥
new easyPromise(promiseCallback)
.then(thenCallback)
複製程式碼

tips: promise.then() 的時候,並沒有馬上執行括號裡面的回撥函式,只是把括號裡面的回撥函式儲存起來.

我們來梳理一下執行流程

  1. 先通過 thenthenCallback 存起來
this.then = function (cb) {
  that.cb = cb
}
複製程式碼

這裡的 cb , 就是上例的 thenCallback 所以其實可以等價於 this.cb = thenCallback

  1. 執行 promise 括號裡的函式,並把事先定義好的 resolve 函式作為引數傳給他
fn(this.resolve)
複製程式碼

這裡的 fn , 就是上例的 promiseCallback

  1. 執行 promiseCallback 我們的邏輯就跳到 promiseCallback 函式內部去
setTimeout(() => {
  resolve("延時執行")
}, 1000)
複製程式碼

邏輯很簡單,就是等待1秒後,執行 resolve 函式, 這個 resolve 哪來的呢?

fn(this.resolve) -> promiseCallback (resolve) -> resolve

  1. 執行 resolve 我們的邏輯就跳到 resolve 函式內部去
that.cb(data)
複製程式碼

這個 that.cb 又是哪來的呢? 就是我們第一步儲存的 then括號裡面的回撥函式,也就是 thenCallback

console.log(data)
複製程式碼

所以就在1秒後輸出 延時執行

最後

好了,以上就是 promise 的核心邏輯,當然還有很多功能沒實現,不過本文的目的是幫助新手更好的瞭解 promise, 不是要實現一個完整的,符合 promise A+規範的 promise, 想要了解更多的童鞋,這裡推薦幾個連結

  1. 阮一峰:ECMAScript 6 入門 - Promise 物件
  2. 深入 Promise(一)——Promise 實現詳解
  3. 淺談Promise之按照Promise/A+規範實現Promise類

如果覺得本文對您有用,請給本文的github加個star,萬分感謝

另外,github上還有其他一些關於前端的教程和元件, 有興趣的童鞋可以看看,你們的支援就是我最大的動力。

相關文章