隔着超薄肉丝进入小说_男女刺激性视频大片_女教师的诱波多野结衣_一级欧美过瘾大片

當(dāng)前位置: 首頁 / 技術(shù)干貨 / 正文
手封MyPromise

2022-12-02

   mypromise

  引子

  面試時如果被問到“如果沒有Promise,能不能自己實現(xiàn)一個”,就是在深度考察對異步的理解了;

  如果你的回答是“能,我封過”,則必然令人刮目相看~

  事實上,作為ES6新增的API,即使沒有,用戶也完全可以基于想要的效果自己去實現(xiàn)一個;

  這里給到大家我個人的實現(xiàn):MyPromise;

  源碼地址

  實現(xiàn)思路

  將then/catch/finally中入?yún)⒌幕卣{(diào)函數(shù)按順序收集到一個隊列中;

  親自實現(xiàn)一下resolve和reject方法;

  一旦實例resolve就將隊列頭部的catch回調(diào)都彈出,一旦實例reject就將隊列頭部的then回調(diào)都彈出,然后拿取隊列頭部的回調(diào)函數(shù)實行起來;

  每次回調(diào)的執(zhí)行結(jié)果即返回值需要繼續(xù)resolve或reject一下,然后繼續(xù)遞歸執(zhí)行上述過程,直到回調(diào)隊列為空;

  接收任務(wù)執(zhí)行器

  當(dāng)我們new出一個MyPromise,并內(nèi)置一個任務(wù)執(zhí)行器函數(shù)的時候,需要在MyPromise的構(gòu)造器中接收任務(wù)執(zhí)行器函數(shù),并同步地、立即地將其執(zhí)行起來;

  要特別注意:任務(wù)執(zhí)行器函數(shù)是同步地跑在主線程的,而不屬于異步回調(diào);

  test.js

  new MyPromise(

  /* 任務(wù)執(zhí)行器:2秒后隨機履約或毀約 */

  (resolve, reject) => {

  setTimeout(() => {

  Math.random() > 0.5 ? resolve("data0") : reject(new Error("一張好人卡"));

  }, 2000);

  }

  )

  MyPromise.js

  class MyPromise {

  constructor(executor) {

  /* 接收任務(wù)執(zhí)行器并立即調(diào)用(同步調(diào)用) */

  this.executor = executor;

  this.executor();

  }

  }

  定義resolve與reject

  任務(wù)執(zhí)行器函數(shù)會在稍后履約(resolve)或毀約(reject)

  因此要告訴MyPromise履約或毀約時具體做什么

  這里我們先做一下簡單的打印

  MyPromise.js

  class MyPromise {

  constructor(executor) {

  /* 接收任務(wù)執(zhí)行器并立即調(diào)用(同步調(diào)用) */

  /* 綁定執(zhí)行器函數(shù)中的resolve與reject */

  this.executor = executor.bind(

  this, //當(dāng)前promise實例

  

  //當(dāng)前promise實例執(zhí)行resolve時,this不變

  MyPromise.doResolve.bind(this),

  

  //當(dāng)前promise實例執(zhí)行reject時,this不變

  MyPromise.doReject.bind(this)

  );

  this.executor();

  }

  

  /* promise實例執(zhí)行resolve */

  static doResolve(data) {

  console.log("doResolve", data);

  }

  

  /* promise實例執(zhí)行reject */

  static doReject(err) {

  console.log("doReject", err);

  }

  }

  

  module.exports = MyPromise;

  明確回調(diào)期望

  明確一下異步任務(wù)履約/毀約后我們希望做什么

  我們希望一旦異步任務(wù)resolve就執(zhí)行then中的回調(diào)

  我們希望一旦異步任務(wù)reject就執(zhí)行catch中的回調(diào)

  我們希望異步任務(wù)無論成功還是失敗,最終都執(zhí)行finally中的回調(diào)

  期望如下:test.js

  const MyPromise = require("./MyPromiseX")

  

  new MyPromise(

  /* 任務(wù)執(zhí)行器:2秒后隨機履約或毀約 */

  (resolve, reject) => {

  setTimeout(() => {

  Math.random() > 0.1 ? resolve("data0") : reject(new Error("一張好人卡"));

  }, 2000);

  }

  )

  .then(

  data => {

  console.log("then1:data=",data)

  return "data from then1"

  // throw new Error("err from then1")

  }

  )

  .catch(

  err => {

  console.log("catch1:err=",err)

  return "data from catch1"

  }

  )

  .finally(

  ()=>console.log("finally:game over!")

  )

  收集回調(diào)隊列

  每一個then中有一個成功回調(diào)

  每一個catch中有一個失敗回調(diào)

  finally中有一個最終回調(diào)

  我們先按順序?qū)⑦@些回調(diào)收集在一個隊列中

  代碼如下:MyPromise.js

  class MyPromise {

  constructor(executor) {

  

  // 回調(diào)隊列

  this.callbacks = [];

  

  /* 接收任務(wù)執(zhí)行器并立即調(diào)用(同步調(diào)用) */

  // 綁定執(zhí)行器函數(shù)中的resolve與reject

  this.executor = executor.bind(

  this, //當(dāng)前promise實例

  

  //當(dāng)前promise實例執(zhí)行resolve時,this不變

  MyPromise.doResolve.bind(this),

  

  //當(dāng)前promise實例執(zhí)行reject時,this不變

  MyPromise.doReject.bind(this)

  );

  

  // 立即調(diào)用任務(wù)執(zhí)行器

  this.executor();

  }

  

  /* promise實例執(zhí)行resolve */

  static doResolve(data) {

  console.log("doResolve", data);

  }

  

  /* promise實例執(zhí)行reject */

  static doReject(err) {

  console.log("doReject", err);

  }

  

  /* 收集成功回調(diào)到隊列 */

  then(onData) {

  // 將來一旦Promise毀約 回調(diào)隊列頭部的所有then回調(diào)都要彈出作廢

  this.callbacks.push({ type: "then", callback: onData });

  return this;

  }

  

  /* 收集失敗回調(diào)到隊列 */

  catch(onErr) {

  // 將來一旦Promise履約 回調(diào)隊列頭部的所有catch回調(diào)都要彈出作廢

  this.callbacks.push({ type: "catch", callback: onErr });

  return this;

  }

  

  /* 收集終點回調(diào)到隊列(此處假設(shè)只有一個終點回調(diào)) */

  finally(onFinish) {

  this.callbacks.push({ type: "finally", callback: onFinish });

  return this;

  }

  }

  

  module.exports = MyPromise;

  此時在測試腳本test.js的末尾打印一下回調(diào)隊列的話,你會看到如下輸出:

  [

  { type: 'then', callback: [Function (anonymous)] },

  { type: 'catch', callback: [Function (anonymous)] },

  { type: 'finally', callback: [Function (anonymous)] }

  ]

  如果來上一堆亂序的then/catch/finally的話,則你會看到如下輸出:

  [

  { type: 'then', callback: [Function (anonymous)] },

  { type: 'then', callback: [Function (anonymous)] },

  { type: 'then', callback: [Function (anonymous)] },

  { type: 'then', callback: [Function (anonymous)] },

  { type: 'catch', callback: [Function (anonymous)] },

  { type: 'catch', callback: [Function (anonymous)] },

  { type: 'then', callback: [Function (anonymous)] },

  { type: 'finally', callback: [Function (anonymous)] }

  ]

  連環(huán)作案(履約或毀約)

  讓我們在每次成功或失敗后,都隨機地繼續(xù)履約或毀約起來!

  test.js

  const MyPromise = require("./MyPromiseX")

  

  const p = new MyPromise(

  /* 任務(wù)執(zhí)行器:2秒后隨機履約或毀約 */

  (resolve, reject) => {

  setTimeout(() => {

  Math.random() > 0.5 ? resolve("data0") : reject(new Error("一張好人卡"));

  }, 2000);

  }

  )

  .then(

  data => {

  console.log("then1:data=",data)

  

  /* 繼續(xù)履約或毀約! */

  return "data from then1"

  // throw new Error("err from then1")

  }

  )

  .then(

  data => {

  console.log("then2:data=",data)

  

  /* 繼續(xù)履約或毀約! */

  return MyPromise.resolve("data from then2")

  // return MyPromise.reject("err from then2")

  }

  )

  .then(

  data => {

  console.log("then3:data=",data)

  

  /* 繼續(xù)履約或毀約! */

  return new MyPromise(

  (resolve,reject) => setTimeout(() => {

  resolve("data from then3")

  // reject("err from then3")

  }, 2000)

  )

  }

  )

  .then(

  /* 這里本質(zhì)繼續(xù)履約了一個undefined */

  data => console.log("then4:data=",data)

  )

  .catch(

  err => {

  console.log("catch1:err=",err)

  

  /* 繼續(xù)履約 */

  return "data from catch1"

  }

  )

  .catch(

  /* 這里本質(zhì)繼續(xù)履約了一個undefined */

  err => console.log("catch2:err=",err)

  )

  .then(

  /* 這里本質(zhì)繼續(xù)履約了一個undefined */

  data => console.log("then5:data=",data)

  )

  .finally(

  /* 這里本質(zhì)繼續(xù)履約了一個undefined */

  ()=>console.log("finally:game over!")

  )

  

  // 打印一下MyPromise對象的回調(diào)隊列

  console.log("p.callbacks",p.callbacks);

  所謂MyPromise.resolve(data)或MyPromise.reject(err)無非也就是newPromise(executor)的一個語法糖而已,實現(xiàn)如下:

  MyPromise.js片段

  /* 語法糖:創(chuàng)建一個立即resolve的Promise對象 */

  static resolve(data) {

  return new MyPromise((resolve) => resolve(data));

  }

  

  /* 語法糖:創(chuàng)建一個立即reject的Promise對象 */

  static reject(err) {

  return new MyPromise((resolve, reject) => reject(err));

  }

  準(zhǔn)備執(zhí)行連環(huán)回調(diào)

  我們無非想要如下效果:

  只要前面的環(huán)節(jié)履約了:在回調(diào)隊列中找出下一個type為then的回調(diào)執(zhí)行起來;

  只要前面的環(huán)節(jié)毀約了:在回調(diào)隊列中找出下一個type為catch的回調(diào)執(zhí)行起來;

  找下一個then回調(diào)前,所有位于它前面的catch都驅(qū)逐先;

  找下一個catch回調(diào)前,所有位于它前面的then都驅(qū)逐先;

  我們來擼碼實現(xiàn)之!

  定義MyPromise狀態(tài)

  class MyPromise {

  /* Promise狀態(tài)定義 */

  static STATUS_PENDING = 0; // 掛起態(tài)

  static STATUS_FULFILLED = 1; // 履約態(tài)

  static STATUS_REJECTED = 2; // 毀約態(tài)

  ...

  }

  定義回調(diào)入?yún)?/p>

  constructor(executor) {

  /* 回調(diào)隊列 + 回調(diào)入?yún)?(JS單線程模型=每次只能有一個回調(diào)被執(zhí)行) */

  this.callbacks = [];

  

  // 定義給回調(diào)傳的入?yún)ⅲ瑹o論是數(shù)據(jù)還是錯誤,我們統(tǒng)稱為cbArg

  this.cbArg = null;

  ...

  }

  定義驅(qū)逐器

  成功時:從回調(diào)隊列頭部把所有的catch驅(qū)逐

  失敗時:從回調(diào)隊列頭部把所有的then驅(qū)逐

  /*

  成功時:從回調(diào)隊列頭部把所有的catch驅(qū)逐

  失敗時:從回調(diào)隊列頭部把所有的then驅(qū)逐

  */

  shiftCallbacksWithType(type) {

  /* 只要回調(diào)隊列中還有回調(diào),就把隊列頭部type為指定類型的回調(diào)彈出去 */

  while (this.callbacks.length && this.callbacks[0].type === type) {

  // 驅(qū)逐一個回調(diào)函數(shù)

  this.callbacks.shift();

  }

  }

  執(zhí)行連環(huán)回調(diào)

  當(dāng)前任履約時

  狀態(tài)設(shè)置為履約態(tài)

  將回調(diào)入?yún)⒃O(shè)置為需要履約的數(shù)據(jù)

  找下一個then里的回調(diào)執(zhí)行起來

  /* promise實例執(zhí)行resolve */

  static doResolve(data) {

  /* 設(shè)置狀態(tài)為履約態(tài) + 設(shè)置回調(diào)時的入?yún)?+ 拉起下一次回調(diào) */

  this.status = MyPromise.STATUS_FULFILLED;

  

  // 回調(diào)入?yún)閿?shù)據(jù)

  this.cbArg = data;

  

  // 拉起下一次then回調(diào)

  setTimeout(() => {

  this.next();

  });

  }

  當(dāng)前任毀約時

  狀態(tài)設(shè)置為毀約態(tài)

  將回調(diào)入?yún)⒃O(shè)置為毀約的原因

  找下一個catch里的回調(diào)執(zhí)行起來

  /* promise實例執(zhí)行reject */

  static doReject(err) {

  /* 設(shè)置狀態(tài)為毀約態(tài) + 設(shè)置回調(diào)時的錯誤 + 拉起下一次回調(diào) */

  this.status = MyPromise.STATUS_REJECTED;

  

  // 回調(diào)入?yún)殄e誤

  this.cbArg = err;

  

  // 拉起下一次catch回調(diào)

  setTimeout(() => {

  this.next();

  });

  }

  執(zhí)行下一次回調(diào)

  整個MyPromise最核心的邏輯來了

  只要當(dāng)前MyPromise為履約態(tài),就驅(qū)逐隊列頭部所有的catch回調(diào)先

  只要當(dāng)前MyPromise為毀約態(tài),就驅(qū)逐隊列頭部所有的then回調(diào)先

  拿取隊列頭部的那個回調(diào)執(zhí)行起來

  next() {

  /* 確定該回調(diào)哪一個callback */

  if (this.status === MyPromise.STATUS_FULFILLED) {

  // 履約時:彈光隊列頭部的catch回調(diào)

  this.shiftCallbacksWithType("catch");

  }

  

  if (this.status === MyPromise.STATUS_REJECTED) {

  // 毀約時:彈光隊列頭部的then回調(diào)

  this.shiftCallbacksWithType("then");

  }

  

  /* 如果回調(diào)隊列已空,則直接結(jié)束程序 */

  if (!this.callbacks.length) {

  console.log("回調(diào)隊列已空");

  return;

  }

  

  /* 拉取回調(diào)隊列頭部的回調(diào)函數(shù)(注意這里無視了type只解構(gòu)出函數(shù)本身) */

  let { callback } = this.callbacks.shift();

  // 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)

  let value = callback(this.cbArg);

  }

  當(dāng)回調(diào)返回value

  test.js片段

  .then(

  data => {

  console.log("then1:data=",data)

  

  /* 繼續(xù)履約或毀約! */

  return "data from then1"

  // throw new Error("err from then1")

  }

  )

  當(dāng)回調(diào)返回一個新的(非MyPromise對象)的普通value時,我們繼續(xù)向后resolve它

  程序會繼續(xù)doResolve,doResolve內(nèi)部會繼續(xù)拉起下一次next

  下一次next找出的回調(diào)還有新的返回值

  遞歸了解一下!歸了解一下!了解一下!解一下!一下!下!

  next() {

  ...

  // 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)

  let value = callback(this.cbArg);

  

  /* 如果回調(diào)函數(shù)返回一個value 繼續(xù)向下resolve(value) */

  if (!(value instanceof MyPromise)) {

  MyPromise.doResolve.call(this, value);

  }

  ...

  }

  當(dāng)回調(diào)拋出錯誤時

  test.js片段

  .then(

  data => {

  console.log("then1:data=",data)

  

  /* 繼續(xù)履約或毀約! */

  // return "data from then1"

  throw new Error("err from then1")

  }

  )

  try-catch起來,把錯誤信息reject一下

  程序會繼續(xù)doReject,doReject內(nèi)部會繼續(xù)拉起下一次next

  下一次next找出的回調(diào)還有新的返回值

  遞歸了解一下!歸了解一下!了解一下!解一下!一下!下!

  next() {

  ...

  /* 拉取回調(diào)隊列頭部的回調(diào)函數(shù)(注意這里無視了type只解構(gòu)出函數(shù)本身) */

  let { callback } = this.callbacks.shift();

  

  /* 防止回調(diào)函數(shù)中throw錯誤 */

  try {

  // 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)

  let value = callback(this.cbArg);

  

  /* 如果回調(diào)函數(shù)返回一個value 繼續(xù)向下resolve(value) */

  if (!(value instanceof MyPromise)) {

  MyPromise.doResolve.call(this, value);

  }else {

  ...

  }

  } catch (err) {

  // 回調(diào)函數(shù)拋出錯誤時相當(dāng)于reject(err)

  MyPromise.doReject.call(this, err);

  }

  }

  當(dāng)回調(diào)返回一個新的MP對象時

  .then(

  data => {

  console.log("then2:data=",data)

  

  /* 繼續(xù)履約或毀約! */

  return MyPromise.resolve("data from then2")

  // return MyPromise.reject("err from then2")

  }

  )

  .then(

  data => {

  console.log("then3:data=",data)

  

  /* 繼續(xù)履約或毀約! */

  return new MyPromise(

  (resolve,reject) => setTimeout(() => {

  resolve("data from then3")

  // reject("err from then3")

  }, 2000)

  )

  }

  )

  首先,MP的構(gòu)造器一定會被調(diào)用!

  構(gòu)造器里有this.executor(),this.executor()里有resolve(data)或reject(err),也就是doResolve(data)或doReject(err)

  不斷遞歸next()找下一次回調(diào)的過程會自發(fā)地跑起

  這個該死的MP對象可能自帶一個回調(diào)隊列

  我們把當(dāng)前MP對象剩余的回調(diào)隊列過戶給它即可

  next() {

  ...

  /* 拉取回調(diào)隊列頭部的回調(diào)函數(shù)(注意這里無視了type只解構(gòu)出函數(shù)本身) */

  let { callback } = this.callbacks.shift();

  

  /* 防止回調(diào)函數(shù)中throw錯誤 */

  try {

  // 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)

  let value = callback(this.cbArg);

  

  /* 如果回調(diào)函數(shù)返回一個value 繼續(xù)向下resolve(value) */

  if (!(value instanceof MyPromise)) {

  ...

  }

  else {

  // 如果回調(diào)函數(shù)返回一個Promise對象

  // 將后續(xù)所有callback過戶給新的Promise對象

  value.callbacks = value.callbacks.concat(this.callbacks);

  }

  } catch (err) {...}

  }

  完整的next函數(shù)

  遞歸inside!

  /*

  從回調(diào)隊列里拉取下一個適當(dāng)?shù)腸allback并回調(diào)之

  這是MyPromise的核心代碼:遞歸inside!

  */

  next() {

  /* 確定該回調(diào)哪一個callback */

  if (this.status === MyPromise.STATUS_FULFILLED) {

  // 履約時:彈光隊列頭部的catch回調(diào)

  this.shiftCallbacksWithType("catch");

  }

  

  if (this.status === MyPromise.STATUS_REJECTED) {

  // 毀約時:彈光隊列頭部的then回調(diào)

  this.shiftCallbacksWithType("then");

  }

  

  /* 如果回調(diào)隊列已空,則直接結(jié)束程序 */

  if (!this.callbacks.length) {

  console.log("回調(diào)隊列已空");

  return;

  }

  

  /* 拉取回調(diào)隊列頭部的回調(diào)函數(shù)(注意這里無視了type只解構(gòu)出函數(shù)本身) */

  let { callback } = this.callbacks.shift();

  

  /* 防止回調(diào)函數(shù)中throw錯誤 */

  try {

  // 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)

  let value = callback(this.cbArg);

  

  /* 如果回調(diào)函數(shù)返回一個value 繼續(xù)向下resolve(value) */

  if (!(value instanceof MyPromise)) {

  MyPromise.doResolve.call(this, value);

  }

  else {

  // 如果回調(diào)函數(shù)返回一個Promise對象

  // 將后續(xù)所有callback過戶給新的Promise對象

  value.callbacks = value.callbacks.concat(this.callbacks);

  }

  } catch (err) {

  // 回調(diào)函數(shù)拋出錯誤時相當(dāng)于reject(err)

  MyPromise.doReject.call(this, err);

  }

  }

  完整代碼

  MyPromise.js

  class MyPromise {

  /* Promise狀態(tài)定義 */

  static STATUS_PENDING = 0; // 掛起態(tài)

  static STATUS_FULFILLED = 1; // 履約態(tài)

  static STATUS_REJECTED = 2; // 毀約態(tài)

  

  constructor(executor) {

  /* 回調(diào)隊列 + 回調(diào)入?yún)?(JS單線程模型=每次只能有一個回調(diào)被執(zhí)行) */

  this.callbacks = [];

  

  // 定義給回調(diào)傳的入?yún)ⅲ瑹o論是數(shù)據(jù)還是錯誤,我們統(tǒng)稱為cbArg

  this.cbArg = null;

  

  /* 綁定執(zhí)行器函數(shù)中的resolve與reject */

  this.executor = executor.bind(

  this, //當(dāng)前promise實例

  

  //當(dāng)前promise實例執(zhí)行resolve時,this不變

  MyPromise.doResolve.bind(this),

  

  //當(dāng)前promise實例執(zhí)行reject時,this不變

  MyPromise.doReject.bind(this)

  );

  

  // 執(zhí)行任務(wù)前先將Promise狀態(tài)設(shè)置為pending

  this.status = MyPromise.STATUS_PENDING;

  

  // 執(zhí)行任務(wù)(任務(wù)中會resolve/doResolve或reject/doReject)

  this.executor();

  }

  

  /* promise實例執(zhí)行resolve */

  static doResolve(data) {

  /* 設(shè)置狀態(tài)為履約態(tài) + 設(shè)置回調(diào)時的入?yún)?+ 拉起下一次回調(diào) */

  this.status = MyPromise.STATUS_FULFILLED;

  

  // 回調(diào)入?yún)閿?shù)據(jù)

  this.cbArg = data;

  

  // 拉起下一次then回調(diào)

  setTimeout(() => {

  this.next();

  });

  }

  

  /* promise實例執(zhí)行reject */

  static doReject(err) {

  /* 設(shè)置狀態(tài)為毀約態(tài) + 設(shè)置回調(diào)時的錯誤 + 拉起下一次回調(diào) */

  this.status = MyPromise.STATUS_REJECTED;

  

  // 回調(diào)入?yún)殄e誤

  this.cbArg = err;

  

  // 拉起下一次catch回調(diào)

  setTimeout(() => {

  this.next();

  });

  }

  

  /*

  成功時:從回調(diào)隊列頭部把所有的catch驅(qū)逐

  失敗時:從回調(diào)隊列頭部把所有的then驅(qū)逐

  */

  shiftCallbacksWithType(type) {

  /* 只要回調(diào)隊列中還有回調(diào),就把隊列頭部type為指定類型的回調(diào)彈出去 */

  while (this.callbacks.length && this.callbacks[0].type === type) {

  // 驅(qū)逐一個回調(diào)函數(shù)

  this.callbacks.shift();

  }

  }

  

  /*

  從回調(diào)隊列里拉取下一個適當(dāng)?shù)腸allback并回調(diào)之

  這是MyPromise的核心代碼:遞歸inside!

  */

  next() {

  /* 確定該回調(diào)哪一個callback */

  if (this.status === MyPromise.STATUS_FULFILLED) {

  // 履約時:彈光隊列頭部的catch回調(diào)

  this.shiftCallbacksWithType("catch");

  }

  

  if (this.status === MyPromise.STATUS_REJECTED) {

  // 毀約時:彈光隊列頭部的then回調(diào)

  this.shiftCallbacksWithType("then");

  }

  

  /* 如果回調(diào)隊列已空,則直接結(jié)束程序 */

  if (!this.callbacks.length) {

  console.log("回調(diào)隊列已空");

  return;

  }

  

  /* 拉取回調(diào)隊列頭部的回調(diào)函數(shù)(注意這里無視了type只解構(gòu)出函數(shù)本身) */

  let { callback } = this.callbacks.shift();

  

  /* 防止回調(diào)函數(shù)中throw錯誤 */

  try {

  // 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)

  let value = callback(this.cbArg);

  

  /* 如果回調(diào)函數(shù)返回一個value 繼續(xù)向下resolve(value) */

  if (!(value instanceof MyPromise)) {

  MyPromise.doResolve.call(this, value);

  }

  else {

  // 如果回調(diào)函數(shù)返回一個Promise對象

  // 將后續(xù)所有callback過戶給新的Promise對象

  value.callbacks = value.callbacks.concat(this.callbacks);

  }

  } catch (err) {

  // 回調(diào)函數(shù)拋出錯誤時相當(dāng)于reject(err)

  MyPromise.doReject.call(this, err);

  }

  }

  

  /* 語法糖:創(chuàng)建一個立即resolve的Promise對象 */

  static resolve(data) {

  return new MyPromise((resolve) => resolve(data));

  }

  

  /* 語法糖:創(chuàng)建一個立即reject的Promise對象 */

  static reject(err) {

  return new MyPromise((resolve, reject) => reject(err));

  }

  

  /* 收集成功回調(diào)到隊列 */

  then(onData) {

  // 將來一旦Promise毀約 回調(diào)隊列頭部的所有then回調(diào)都要彈出作廢

  this.callbacks.push({ type: "then", callback: onData });

  return this;

  }

  

  /* 收集失敗回調(diào)到隊列 */

  catch(onErr) {

  // 將來一旦Promise履約 回調(diào)隊列頭部的所有catch回調(diào)都要彈出作廢

  this.callbacks.push({ type: "catch", callback: onErr });

  return this;

  }

  

  /* 收集終點回調(diào)到隊列(此處假設(shè)只有一個終點回調(diào)) */

  finally(onFinish) {

  this.callbacks.push({ type: "finally", callback: onFinish });

  return this;

  }

  }

  

  module.exports = MyPromise;

  測試代碼test.js

  const MyPromise = require("./MyPromise3")

  

  const p = new MyPromise(

  /* 任務(wù)執(zhí)行器:2秒后隨機履約或毀約 */

  (resolve, reject) => {

  setTimeout(() => {

  Math.random() > 0.1 ? resolve("data0") : reject(new Error("一張好人卡"));

  }, 2000);

  }

  )

  .then(

  data => {

  console.log("then1:data=",data)

  

  /* 繼續(xù)履約或毀約! */

  return "data from then1"

  // throw new Error("err from then1")

  }

  )

  .then(

  data => {

  console.log("then2:data=",data)

  

  /* 繼續(xù)履約或毀約! */

  return MyPromise.resolve("data from then2")

  // return MyPromise.reject("err from then2")

  }

  )

  .then(

  data => {

  console.log("then3:data=",data)

  

  /* 繼續(xù)履約或毀約! */

  return new MyPromise(

  (resolve,reject) => setTimeout(() => {

  resolve("data from then3")

  // reject("err from then3")

  }, 2000)

  )

  }

  )

  .then(

  /* 這里本質(zhì)繼續(xù)履約了一個undefined */

  data => console.log("then4:data=",data)

  )

  .catch(

  err => {

  console.log("catch1:err=",err)

  

  /* 繼續(xù)履約 */

  return "data from catch1"

  }

  )

  .catch(

  /* 這里本質(zhì)繼續(xù)履約了一個undefined */

  err => console.log("catch2:err=",err)

  )

  .then(

  /* 這里本質(zhì)繼續(xù)履約了一個undefined */

  data => console.log("then5:data=",data)

  )

  .finally(

  /* 這里本質(zhì)繼續(xù)履約了一個undefined */

  ()=>console.log("finally:game over!")

  )

  

  // 打印一下MyPromise對象的回調(diào)隊列

  console.log("p.callbacks",p.callbacks);

  測試效果

  https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5c47910678fd41acba1eed2ea02bbabb~tplv-k3u1fbpfcp-watermark.image?

好程序員公眾號

  • · 剖析行業(yè)發(fā)展趨勢
  • · 匯聚企業(yè)項目源碼

好程序員開班動態(tài)

More+
  • HTML5大前端 <高端班>

    開班時間:2021-04-12(深圳)

    開班盛況

    開班時間:2021-05-17(北京)

    開班盛況
  • 大數(shù)據(jù)+人工智能 <高端班>

    開班時間:2021-03-22(杭州)

    開班盛況

    開班時間:2021-04-26(北京)

    開班盛況
  • JavaEE分布式開發(fā) <高端班>

    開班時間:2021-05-10(北京)

    開班盛況

    開班時間:2021-02-22(北京)

    開班盛況
  • Python人工智能+數(shù)據(jù)分析 <高端班>

    開班時間:2021-07-12(北京)

    預(yù)約報名

    開班時間:2020-09-21(上海)

    開班盛況
  • 云計算開發(fā) <高端班>

    開班時間:2021-07-12(北京)

    預(yù)約報名

    開班時間:2019-07-22(北京)

    開班盛況
IT培訓(xùn)IT培訓(xùn)
在線咨詢
IT培訓(xùn)IT培訓(xùn)
試聽
IT培訓(xùn)IT培訓(xùn)
入學(xué)教程
IT培訓(xùn)IT培訓(xùn)
立即報名
IT培訓(xùn)

Copyright 2011-2023 北京千鋒互聯(lián)科技有限公司 .All Right 京ICP備12003911號-5 京公網(wǎng)安備 11010802035720號