【庫】Promise的簡便實現,15行程式碼優雅解決非同步巢狀

清一色天空發表於2019-02-27

該Promise的實現,只解決非同步巢狀的問題,並沒有其他All之類的方法哦。

一、類的定義階段

class Pro {
  constructor (fn) {
    this.arr = []
    this.count = -1
    fn(this)
  }
  then (r) {
    if (typeof (r) === `function`) {
      this.arr.push(r)
      return this
    } else {
      this.arr[++this.count] && this.arr[this.count](this, r)
    }
  }
}
複製程式碼

該程式碼只有15行左右,要再短點也不是不可,但越短的程式碼只有兩種可能,要麼easy,要麼difficulty,該類應該算是前者,再配合debugger還是比較容易看得懂的。


二、呼叫階段

new Pro(fn => {
  setTimeout(() => {
    let data = 1 // 舉例資料為1
    console.log(`A拿到資料後,進行處理`, data)
    console.log(`A將資料傳到下一個ajax`)
    console.log(`A-------------`)
    fn.then(data)
  }, 500)
}).then((fn, r) => {
  console.log(`A上一個資料是`, r)
  setTimeout(() => {
    let data = 2
    console.log(`A拿到資料後,進行處理`, data)
    console.log(`A將資料傳到下一個ajax`)
    console.log(`A-------------`)
    fn.then(data)
  }, 500)
}).then((fn, r) => {
  console.log(`A上一個資料是`, r)
  setTimeout(() => {
    let data = 3
    console.log(`A拿到資料後,進行處理`, data)
    console.log(`A將資料傳到下一個ajax`)
    console.log(`A-------------`)
    fn.then(data)
  }, 500)
}).then((fn, r) => {
  console.log(`A上一個資料是`, r)
  setTimeout(() => {
    let data = 4
    console.log(`A拿到資料後,進行處理`, data)
  }, 500)
})

複製程式碼

以下是返回的結果

這裡寫圖片描述

這裡就達到了巢狀的目的,並且程式碼上沒有難看的階梯狀結構。


三、多非同步呼叫檢測

new Pro(fn => {
  setTimeout(() => {
    let data = 1 // 舉例資料為1
    console.log(`A拿到資料後,進行處理`, data)
    console.log(`A將資料傳到下一個ajax`)
    console.log(`A-------------`)
    fn.then(data)
  }, 500)
}).then((fn, r) => {
  console.log(`A上一個資料是`, r)
  setTimeout(() => {
    let data = 2
    console.log(`A拿到資料後,進行處理`, data)
    console.log(`A將資料傳到下一個ajax`)
    console.log(`A-------------`)
    fn.then(data)
  }, 500)
}).then((fn, r) => {
  console.log(`A上一個資料是`, r)
  setTimeout(() => {
    let data = 3
    console.log(`A拿到資料後,進行處理`, data)
    console.log(`A將資料傳到下一個ajax`)
    console.log(`A-------------`)
    fn.then(data)
  }, 500)
}).then((fn, r) => {
  console.log(`A上一個資料是`, r)
  setTimeout(() => {
    let data = 4
    console.log(`A拿到資料後,進行處理`, data)
  }, 500)
})

new Pro(fn => {
  setTimeout(() => {
    let data = 11
    console.log(`B拿到資料後,進行處理`, data)
    console.log(`B將資料傳到下一個ajax`)
    console.log(`B-------------`)
    fn.then(data)
  }, 500)
}).then((fn, r) => {
  console.log(`B上一個資料是`, r)
  setTimeout(() => {
    let data = 22
    console.log(`B拿到資料後,進行處理`, data)
    console.log(`B將資料傳到下一個ajax`)
    console.log(`B-------------`)
    fn.then(data)
  }, 500)
}).then((fn, r) => {
  console.log(`B上一個資料是`, r)
  setTimeout(() => {
    let data = 33
    console.log(`B拿到資料後,進行處理`, data)
    console.log(`B將資料傳到下一個ajax`)
    console.log(`B-------------`)
    fn.then(data)
  }, 500)
}).then((fn, r) => {
  console.log(`B上一個資料是`, r)
  setTimeout(() => {
    let data = 44
    console.log(`B拿到資料後,進行處理`, data)
  }, 500)
})

複製程式碼

以下是返回的結果

這裡寫圖片描述

返回成功,A為A的呼叫棧,B為B的呼叫棧,沒有互相混淆。


關於

make:o︻そ╆OVE▅▅▅▆▇◤(清一色天空)

blog:http://blog.csdn.net/mcky_love

掘金:https://juejin.im/user/59fbe6c66fb9a045186a159a/posts


結束語

成功之後,即可對該類進行二次封裝,如工廠模式下,以return物件來實現Promise.all()等方法。所有的實現原理並不一定要以原始碼來實現,萬一你有更好的思路呢?(∩_∩)

相關文章