手寫 promise 之路

手寫 promise 之路

  1. 先看一下我們正常的使用場(chǎng)景
var test = new TestPromise((res,rej)=> {
  setTimeout(() => {
      res(99999)
  },1000)
})
test.then((a) => {
  console.log(1111,a)
})
  1. 這是按照使用場(chǎng)景的第一次嘗試的代碼
class TestPromise {
  constructor(callback) {
    this.status = 'pending'
    callback(this.resolve, this.reject)
  }
  resolve = (data) => {
    if(this.status == 'pending') {
      this.status = 'resolve'
      console.log('進(jìn)入resolve')
      return data
    }
  }
  reject = (data) => {
    if(this.status == 'pending') {
      this.status = 'reject'
      console.log('進(jìn)入reject')
      return data
    }
  }
  then = (resolveResult) => {
    console.log(this.status)
    if(this.status == 'resolve') {
      resolveResult()
    }
  }
}
  1. 運(yùn)行一下看一下打印結(jié)果
pending
進(jìn)入resolve
  1. 此時(shí)發(fā)現(xiàn)會(huì)先執(zhí)行我們的 then 方法,然后在執(zhí)行的 resolve 方法這和我們預(yù)期的完全不一樣, 因?yàn)榘凑疹A(yù)期應(yīng)該是等 resolve 后在執(zhí)行 then 方法,這個(gè)時(shí)候才想到是缺了發(fā)布訂閱的通知,所以下面的步驟應(yīng)該是能有一個(gè)發(fā)布訂閱的消息通知。網(wǎng)上關(guān)于發(fā)布訂閱這一塊已經(jīng)說的很多了,這里就不綴余了。代碼如下:
/**
 * 事件監(jiān)聽
 */
let keyCount = 1;
export default class Monitor {
  list: any = {};
  // 注冊(cè)
  on = (fun: any = () => {}) => {
    const key = `key-${keyCount++}-${+new Date()}`;
    this.list[key] = fun;
    return {
      key,
      off: () => {
        this.off(key);
      }
    };
  };
  // 注冊(cè)一次執(zhí)行后關(guān)閉
  once = (fn: any = () => {}) => {
    const _id = this.on((res: any) => {
      _id.off();
      return fn(res);
    });
    return _id;
  };
  // // 刪除
  off = (key: string | number) => {
    delete this.list[key];
    return true;
  };
  go = (...res: any) => {
    const resList = [];
    for (const key in this.list) {
      try {
        resList.push(this.list[key](...res));
      } catch (e) {
        resList.push(new Error(e));
      }
    }
    return resList;
  };
  // // 刪除所有事件注冊(cè)
  offAll = () => {
    this.list = {};
    return true;
  };
}

  1. 加上兩個(gè)數(shù)組用來存儲(chǔ)事件(傳統(tǒng)的是用對(duì)象來當(dāng)事件中心,但是我們不需要定義事件的名稱,所以就直接用兩個(gè)數(shù)組來儲(chǔ)存就行了,因?yàn)槲覀兊氖录椭挥袃蓚€(gè))
class TestPromise {
  constructor(callback) {
    this.status = "pending";
    this.resolveEventArr = [];
    this.rejectEventArr = [];
    callback(this.resolve, this.reject);
  }
  resolve = (data) => {
    if (this.status == "pending") {
      this.status = "resolve";
      this.resolveEventArr.forEach((item) => item(data));
      console.log("進(jìn)入resolve");
    }
  };
  reject = (data) => {
    if (this.status == "pending") {
      this.status = "reject";
      this.rejectEventArr.forEach((item) => item(data));
      console.log("進(jìn)入reject");
    }
  };
  then = (resolveEvent, rejectEvent) => {
    console.log(this.status);
    if (this.status == "pending") {
      this.resolveEventArr.push(resolveEvent);
      this.rejectEventArr.push(rejectEvent);
    }
  };
}
var test = new TestPromise((res, rej) => {
  setTimeout(() => {
    res(99999);
  }, 1000);
});
test.then((a) => {
  console.log(1111, a);
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容