国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【JavaScript】手寫Promise

這篇具有很好參考價值的文章主要介紹了【JavaScript】手寫Promise。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

?? 個人主頁:不叫貓先生
???♂? 作者簡介:2022年度博客之星前端領(lǐng)域TOP 2,前端領(lǐng)域優(yōu)質(zhì)作者、阿里云專家博主,專注于前端各領(lǐng)域技術(shù),共同學(xué)習(xí)共同進步,一起加油呀!
??優(yōu)質(zhì)專欄:vue3從入門到精通、TypeScript從入門到實踐
?? 資料領(lǐng)?。呵岸诉M階資料可以找我免費領(lǐng)取
?? 摸魚學(xué)習(xí)交流:我們的宗旨是在工作中摸魚,摸魚中進步,期待大佬一起來摸魚(文末有我wx或者私信)。

面試中經(jīng)常會被問到你會手寫Promise嗎?本文帶你手?jǐn)]Promsie

基礎(chǔ)回顧

先回顧一下Promise的基本使用方法及特點

  • promise三個狀態(tài):進?中(pending)、已完成(fulfilled)、已拒絕(rejected)

  • 處理promise異常的三種方式:

    • 通過promise的then的第二個參數(shù)
    • 通過.catch處理
    • 通過try…catch處理
  • promise狀態(tài)處理

    • 處于等待態(tài)時,promise 需滿?以下條件:可以變?yōu)椤敢淹瓿伞够颉敢丫芙^」
    • 處于已完成時,promise 需滿?以下條件:不能遷移?其他任何狀態(tài);必須擁有?個不可變的值
    • 處于已拒絕時,promise 需滿?以下條件:不能遷移?其他任何狀態(tài);必須擁有?個不可變的原

一、聲明Promise類,并進行初始化操作

首先定義一個Promise類,然后進行一些初始化操作。

  • 接收一個回調(diào)函數(shù)callback,回調(diào)函數(shù)包含兩個參數(shù),一個resolve,一個reject
  • 初始化狀態(tài)為pending
  • 初始化成功狀態(tài)的值
  • 初始化失敗狀態(tài)的值
  • 定義resolve函數(shù)
  • 定義reject函數(shù)
class MyPromise {
  constructor(callback) {
    // 初始化狀態(tài)為 pending
    this.status = 'pending';
    // 初始化成功狀態(tài)的值
    this.value = undefined;
    // 初始化失敗狀態(tài)的值
    this.reason = undefined;

    // 定義 resolve 函數(shù)
    const resolve = value => {
      if (this.status === 'pending') {
        // 更新狀態(tài)為 resolved
        this.status = 'resolved';
        // 存儲成功狀態(tài)的值
        this.value = value;
      }
    };

    // 定義 reject 函數(shù)
    const reject = reason => {
      if (this.status === 'pending') {
        // 更新狀態(tài)為 rejected
        this.status = 'rejected';
        // 存儲失敗狀態(tài)的值
        this.reason = reason;
      }
    };

    // 調(diào)用回調(diào)函數(shù),將 resolve 和 reject 傳遞給它
    callback(resolve, reject);
  }
}

二、then方法

接下來定義Promsie類中then函數(shù)。

  • 首先創(chuàng)建一個Promise對象,根據(jù)Promise的狀態(tài)來執(zhí)行不同的回調(diào)函數(shù)。then函數(shù)接收兩個參數(shù),一個onResolved(Promise 的狀態(tài)為成功時候調(diào)用),一個onRejected(Promise 的狀態(tài)為失敗時候調(diào)用)。
  • then函數(shù)返回一個新的Promsie對象,它的值取決于回調(diào)函數(shù)的返回值
  • 如果當(dāng)前狀態(tài)是pending,需要將onResolved,onRejected回調(diào)保存起來,等異步結(jié)束之后再執(zhí)行
class MyPromise {
 then(onResolved, onRejected) {
    // 創(chuàng)建一個新的 Promise 對象
    const newPromise = new MyPromise((resolve, reject) => {
      // 如果當(dāng)前 Promise 的狀態(tài)為 resolved
      if (this.status === 'resolved') {
        try {
          // 執(zhí)行 onResolved 回調(diào)函數(shù)
          const x = onResolved(this.value);
          // 處理返回值
          resolve(x);
        } catch (error) {
          // 如果回調(diào)函數(shù)拋出異常,將異常作為失敗狀態(tài)的值
          reject(error);
        }
      }

      // 如果當(dāng)前 Promise 的狀態(tài)為 rejected
      if (this.status === 'rejected') {
        try {
          // 執(zhí)行 onRejected 回調(diào)函數(shù)
          const x = onRejected(this.reason);
          // 處理返回值
          resolve(x);
        } catch (error) {
          // 如果回調(diào)函數(shù)拋出異常,將異常作為失敗狀態(tài)的值
          reject(error);
        }
      }

      // 如果當(dāng)前 Promise 的狀態(tài)為 pending
      if (this.status === 'pending') {
        // 將 onResolved 和 onRejected 保存起來
        // 等待異步操作完成后再執(zhí)行
        this.onResolvedCallbacks.push(() => {
          try {
            const x = onResolved(this.value);
            resolve(x);
          } catch (error) {
            reject(error);
                });

    this.onRejectedCallbacks.push(() => {
      try {
        const x = onRejected(this.reason);
        resolve(x);
      } catch (error) {
        reject(error);
      }
    });
  }
});
// 返回新的 Promise 對象
return newPromise;
}

三、catch方法

將 catch 方法轉(zhuǎn)化為 then 方法的一個語法糖,就可以實現(xiàn)啦。到這里我們基本已經(jīng)實現(xiàn)了一個Promise

class MyPromise {
  catch(onRejected) {
    return this.then(null, onRejected);
  }
}

四、基礎(chǔ)完整版代碼

class MyPromise {
  constructor(callback) {
    // 初始化狀態(tài)為 pending
    this.status = 'pending';
    // 初始化成功狀態(tài)的值
    this.value = undefined;
    // 初始化失敗狀態(tài)的值
    this.reason = undefined;
    // 存儲成功狀態(tài)的回調(diào)函數(shù)
    this.onResolvedCallbacks = [];
    // 存儲失敗狀態(tài)的回調(diào)函數(shù)
    this.onRejectedCallbacks = [];

    // 定義 resolve 函數(shù)
    const resolve = value => {
      if (this.status === 'pending') {
        // 更新狀態(tài)為 resolved
        this.status = 'resolved';
        // 存儲成功狀態(tài)的值
        this.value = value;
        // 執(zhí)行所有成功狀態(tài)的回調(diào)函數(shù)
        this.onResolvedCallbacks.forEach(cb => cb());
      }
    };

    // 定義 reject 函數(shù)
    const reject = reason => {
      if (this.status === 'pending') {
        // 更新狀態(tài)為 rejected
        this.status = 'rejected';
        // 存儲失敗狀態(tài)的值
        this.reason = reason;
        // 執(zhí)行所有失敗狀態(tài)的回調(diào)函數(shù)
        this.onRejectedCallbacks.forEach(cb => cb());
      }
    };

    // 調(diào)用回調(diào)函數(shù),將 resolve 和 reject 傳遞給它
    callback(resolve, reject);
  }

    // 創(chuàng)建一個新的 Promise 對象
    const promise2 = new MyPromise((resolve, reject) => {
      // 如果當(dāng)前 Promise 的狀態(tài)為 resolved
      if (this.status === 'resolved') {
        try {
          // 執(zhí)行 onResolved 回調(diào)函數(shù)
          const x = onResolved(this.value);
          // 處理返回值
          resolve(x);
        } catch
      (error) {
        // 如果回調(diào)函數(shù)拋出異常,則將異常作為新 Promise 的失敗狀態(tài)的值
        reject(error);
      }
    });
  }

  // 如果當(dāng)前 Promise 的狀態(tài)為 rejected
  if (this.status === 'rejected') {
    try {
      // 執(zhí)行 onRejected 回調(diào)函數(shù)
      const x = onRejected(this.reason);
      // 處理返回值
      resolve(x);
    } catch (error) {
      // 如果回調(diào)函數(shù)拋出異常,則將異常作為新 Promise 的失敗狀態(tài)的值
      reject(error);
    }
  }

  // 如果當(dāng)前 Promise 的狀態(tài)為 pending
  if (this.status === 'pending') {
    // 將 onResolved 和 onRejected 回調(diào)函數(shù)保存起來,等待異步操作完成后再執(zhí)行
    this.onResolvedCallbacks.push(() => {
      try {
        const x = onResolved(this.value);
        resolve(x);
      } catch (error) {
        reject(error);
      }
    });

    this.onRejectedCallbacks.push(() => {
      try {
        const x = onRejected(this.reason);
        resolve(x);
      } catch (error) {
        reject(error);
      }
    });
  }
});

  // 返回新的 Promise 對象
  return promise2;
}
catch(onRejected) {
   return this.then(null, onRejected);
   }
}

五、案例測試

生成一個myPromsie對象,然后用then方法進行鏈?zhǔn)秸{(diào)用。

		const promise = new MyPromise((resolve, reject) => {
			setTimeout(() => {
				console.log('1')
				resolve('成功')
			}, 1000)
		})
		promise.then(value => {
			console.log('2')
			return "第一次"
		}).then(value => {
			console.log('3')
			return new MyPromise((resolve, reject) => {
				setTimeout(() => {
					resolve('第二次處理結(jié)果');
				}, 1000);
			});
		}).then(value => {
			console.log(value);
			throw new Error('拋出異常');
		}).catch(error => {
			console.log(error);
		});

【JavaScript】手寫Promise

六、問題

1. 為什么then函數(shù)中需要考慮Promise狀態(tài)為pending的情況?

當(dāng) then 方法被調(diào)用時,我們首先需要判斷原始 Promise 對象的狀態(tài)。

  • 如果原始 Promise 對象的狀態(tài)為 fulfilled,那么我們就可以直接執(zhí)行成功回調(diào)函數(shù),并將成功狀態(tài)的值作為參數(shù)傳遞給它。
  • 如果原始 Promise 對象的狀態(tài)為 rejected,那么我們就可以直接執(zhí)行失敗回調(diào)函數(shù),并將失敗原因作為參數(shù)傳遞給它。
  • 但是,如果原始 Promise 對象的狀態(tài)為 pending,那么我們就需要等待原始 Promise 對象的狀態(tài)發(fā)生變化,再執(zhí)行相應(yīng)的操作。

2. 當(dāng)then函數(shù)傳的參數(shù)不是函數(shù)怎么辦?

為了避免then函數(shù)傳的參數(shù)不是函數(shù),需要對上面代碼稍微優(yōu)化一下

  then(onResolved, onRejected) {
      	onResolved = typeof onResolved === "function" ? onResolved : (value) => value;
		onRejected = typeof onRejected === "function" ? onRejected : (reason) => { throw reason };
		//其他邏輯
  }

3. onResolvedCallbacks 和 onRejectedCallbacks 什么時候清空?

在調(diào)用then函數(shù)中,當(dāng)Promise的狀態(tài)為pending時候,會把onResolved和onRejected回調(diào)放到各自回調(diào)函數(shù)隊列中,等狀態(tài)改變(即在執(zhí)行resolve函數(shù)/reject函數(shù))時候,將 onResolvedCallbacks ,this.onRejectedCallbacks 循環(huán)調(diào)用。當(dāng)Promise狀態(tài)pending時候,就將 onResolvedCallbacks 和 onRejectedCallbacks 置空。所以優(yōu)化上面代碼如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-453455.html

then(onResolved,onRejected){
       if (this.status == "pending") {
						this.onResolvedCallbacks.push(() => {
							if (this.status == "resolved") {
								try {
									const x = onResolved(this.value)
									resolve(x)
								} catch (error) {
									reject(error)
								}
							}
						})
						this.onRejectedCallbacks.push(() => {
							if (this.status == "rejected") {
								try {
									const x = onRejected(this.reason)
									resolve(x)
								} catch (error) {
									reject(error)
								}
							}
						})
					} else {
						// 執(zhí)行完所有回調(diào)函數(shù)之后,清空回調(diào)數(shù)組
						this.onResolvedCallbacks = [];
						this.onRejectedCallbacks = [];
					}
}

七、優(yōu)化后完整代碼

	<script>

		class MyPromise {
			constructor(callback) {
				this.status = "pending";
				this.value = "";
				this.reason = "";
				// 存儲成功狀態(tài)的回調(diào)函數(shù)
				this.onResolvedCallbacks = [];
				// 存儲失敗狀態(tài)的回調(diào)函數(shù)
				this.onRejectedCallbacks = [];
				const resolve = (value) => {
					if (this.status == "pending") {
						this.status = "resolved"
						this.value = value;
						this.onResolvedCallbacks.forEach((fn) => fn());
					}
				}
				const reject = (reason) => {
					if (this.status == "pending") {
						this.status = "rejected"
						this.reason = reason;
						this.onRejectedCallbacks.forEach((fn) => fn());
					}
				}
				try {
					callback(resolve, reject);
				} catch (error) {
					reject(error);
				}

			}

			then(onResolved, onRejected) {
				onResolved = typeof onResolved === "function" ? onResolved : (value) => value;
				onRejected = typeof onRejected === "function" ? onRejected : (reason) => { throw reason };
				const promise2 = new MyPromise((resolve, reject) => {
					if (this.status == "resolved") {
						console.log('1111111111')
						try {
							const x = onResolved(this.value)
							resolve(x)
						} catch (error) {
							reject(error)
						}
					}
					if (this.status == "rejected") {
						console.log('2222222')
						try {
							const x = onRejected(this.reason)
							resolve(x)
						} catch (error) {
							reject(error)
						}
					}
					if (this.status == "pending") {
						console.log('333333333333')
						this.onResolvedCallbacks.push(() => {
							if (this.status == "resolved") {
								try {
									const x = onResolved(this.value)
									resolve(x)
								} catch (error) {
									reject(error)
								}
							}
						})
						this.onRejectedCallbacks.push(() => {
							if (this.status == "rejected") {
								try {
									const x = onRejected(this.reason)
									resolve(x)
								} catch (error) {
									reject(error)
								}
							}
						})
					} else {
						// 執(zhí)行完所有回調(diào)函數(shù)之后,清空回調(diào)數(shù)組
						this.onResolvedCallbacks = [];
						this.onRejectedCallbacks = [];
					}
				})
				return promise2
			}
			catch(onRejected) {
				return this.then(null, onRejected)
			}
		}

		const promise = new MyPromise((resolve, reject) => {
			// setTimeout(() => {
			// 	console.log('1')
				resolve('成功')
			// }, 1000)
		})
		promise.then(1).
		then(value => {
			// console.log('2')
			// return "第一次"
			// setTimeout(() => {
				console.log('1')
					// return "第一次"
			// },1000)
		}).then(value => {
			console.log('3')
			return new MyPromise((resolve, reject) => {
				setTimeout(() => {
					resolve('第二次處理結(jié)果');
				}, 1000);
			});
		}).then(value => {
			console.log(value);
			throw new Error('拋出異常');
		}).catch(error => {
			console.log(error);
		});
	</script>

1. 處理promsie異常的三種方式

```javascript
function promise3() {
 return new Promise(function(resolve, reject) {
 var random = Math.random() * 10; // 隨機?個 1 - 10 的數(shù)字
 setTimeout(function() {
      if (random >= 5) {
          resolve(random);
      } else {
          reject(random);
      } 
    }, 1000);
 });
}
var onResolve = function(val) {
 console.log('已完成:輸出的數(shù)字是', val);
};
var onReject = function(val) {
 console.log('已拒絕:輸出的數(shù)字是', val);
}
// promise 的 then 接收兩個函數(shù),第?個參數(shù)為 resolve 后執(zhí)?,第?個函數(shù)為 reject 后執(zhí)?
promise().then(onResolve, onReject);
// 也可以通過 .catch ?法攔截狀態(tài)變?yōu)橐丫芙^時的 promise
promise().catch(onReject).then(onResolve);
// 也可以通過 try catch 進?攔截狀態(tài)變?yōu)橐丫芙^的 promise
try {
 promise().then(onResolve);
} catch (e) {
 onReject(e);
}

到了這里,關(guān)于【JavaScript】手寫Promise的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 深入理解 JavaScript Promise

    深入理解 JavaScript Promise

    JavaScript中的Promise是一種處理異步操作的機制,它提供了一種優(yōu)雅的方式來處理回調(diào)函數(shù)地獄和異步代碼的流程控制。本文將深入介紹JavaScript中的Promise,幫助讀者更好地理解和應(yīng)用Promise。 Promise是一個代表異步操作的對象,它可以有三種狀態(tài):pending(進行中)、fulfilled(已

    2024年02月09日
    瀏覽(25)
  • JavaScript 之 promise

    JavaScript 之 promise

    封裝和調(diào)用不是同一個人,不清楚如何調(diào)用 設(shè)計者不好設(shè)計,調(diào)用者調(diào)用很麻煩 從一個實際的例子來作為切入點: 調(diào)用一個函數(shù),這個函數(shù)中發(fā)送網(wǎng)絡(luò)請求(可以用定時器來模擬) 如果發(fā)送網(wǎng)絡(luò)請求成功了,那么告知調(diào)用者發(fā)送成功,并且將相關(guān)數(shù)據(jù)返回過去 如果發(fā)送網(wǎng)

    2024年01月21日
    瀏覽(17)
  • [JavaScript理論學(xué)習(xí)] 什么是Promise (含如何判斷一個值是Promise)

    本文旨在對 Promise 的規(guī)范進行解釋, 便于讀者在學(xué)習(xí) Promise 的過程中梳理 Promise 之間的操作關(guān)系, 不對具體的代碼實現(xiàn)和Promise用法進行解釋. 比如, 為什么 [MDN-await] 中要提及一個 thenable 對象, 而且這個 thenable 對象 還可以和 Promise 實例 一樣使用 await 等待處理, 這就涉及到了下面

    2024年02月09日
    瀏覽(21)
  • JavaScript如何解決返回[object Promise]

    當(dāng)使用JavaScript中的Promise時,當(dāng)您嘗試訪問Promise的值時,您可能會看到返回值為 [object Promise] 的情況。這是因為Promise是一種異步操作,它不能立即返回結(jié)果,而是需要等待操作完成后返回結(jié)果。 要訪問Promise的值,您需要使用Promise的then()方法,該方法接受一個回調(diào)函數(shù)作為參

    2024年02月12日
    瀏覽(20)
  • [javascript核心-04]徹底弄懂Promise異步編程

    本文github地址:JavaScript_Interview_Everything 大前端知識體系與面試寶典,從前端到后端,全棧工程師,成為六邊形戰(zhàn)士 1.1. 快速上手 01快手上手.js 02.若傳入的是另一個promise對象,則狀態(tài)由傳入的promise對象決定 03.若傳入了一個實現(xiàn)了 then 方法的對象,則執(zhí)行該then方法且由此方法

    2024年02月08日
    瀏覽(22)
  • JavaScript 異步解決方案 Promise 全解析(轉(zhuǎn)載)

    Promise 是一個 JS 的異步編程解決方案,解決了傳統(tǒng)異步編程回調(diào)地獄的問題。 從語義上來說: Promise 是一個向外部傳達異步編程操作消息的對象。 JS里一個promise可以有以下幾種基本狀態(tài): nothing happened yet \\\"locked in\\\" to another promise fulfilled rejected 其中{1,2}為 pending ,{3,4}為 settl

    2024年02月08日
    瀏覽(25)
  • 深入學(xué)習(xí)JavaScript系列(七)——Promise async/await generator

    深入學(xué)習(xí)JavaScript系列(七)——Promise async/await generator

    本篇屬于本系列第七篇 第一篇:#深入學(xué)習(xí)JavaScript系列(一)—— ES6中的JS執(zhí)行上下文 第二篇:# 深入學(xué)習(xí)JavaScript系列(二)——作用域和作用域鏈 第三篇:# 深入學(xué)習(xí)JavaScript系列(三)——this 第四篇:# 深入學(xué)習(xí)JavaScript系列(四)——JS閉包 第五篇:# 深入學(xué)習(xí)JavaScrip

    2023年04月08日
    瀏覽(33)
  • 【前端異?!縅avaScript錯誤處理:分析 Uncaught(in promise) error

    【前端異常】JavaScript錯誤處理:分析 Uncaught(in promise) error

    在開發(fā)過程中,JavaScript的錯誤處理是一個老生常談的話題。當(dāng)應(yīng)用程序發(fā)生未捕獲的異常時,Uncaught(in promise) error是其中最常見的錯誤類型。這篇文章將從多個方面詳細闡述這種錯誤類型的原因與解決方案。 Promise是一種用于異步編程的原生JavaScript對象。它提供了一種處理異

    2024年02月05日
    瀏覽(103)
  • JavaScript 手寫代碼 第四期

    我們在日常開發(fā)過程中,往往都是取出來直接用,從來不思考代碼的底層實現(xiàn)邏輯,但當(dāng)我開始研究一些底層的東西的時候,才開始理解了JavaScript每個方法和函數(shù)的底層實現(xiàn)思路,我認(rèn)為這可以很好的提高我們的代碼水平和邏輯思維。 簡單來說,就是將多維數(shù)組轉(zhuǎn)換為一維

    2024年02月10日
    瀏覽(21)
  • JavaScript 手寫題

    JavaScript 手寫題

    全排列(力扣原題) 要求以數(shù)組的形式返回字符串參數(shù)的所有排列組合。 注意: instanceof 如果 target 為基本數(shù)據(jù)類型直接返回 false 判斷 Fn.prototype 是否在 target 的隱式原型鏈上 Array.prototype.map map 中的 exc 接受三個參數(shù),分別是: 元素值、元素下標(biāo)和原數(shù)組 map 返回的是一個新的

    2024年02月10日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包