首頁  >  文章  >  web前端  >  建構 XPromise:深入研究自訂 JavaScript Promise

建構 XPromise:深入研究自訂 JavaScript Promise

Linda Hamilton
Linda Hamilton原創
2024-10-26 13:40:03725瀏覽

JavaScript 以其非同步特性而聞名,可以在不阻塞其他進程的情況下實現資料擷取、動畫和檔案處理等操作。 Promise 是優雅地處理非同步操作的核心,讓我們的程式碼更乾淨、更容易管理。這個專案 XPromise 是 JavaScript Promise 的自訂實現,幫助我們探索 Promise 機制的內部運作原理。

您可以在 GitHub 上查看完整的實作。

什麼是承諾?

JavaScript 中的 Promise 是一個特殊的對象,表示非同步操作的最終完成或失敗。使用 Promises,我們可以將操作排隊以在任務完成後運行,即使我們不知道任務何時完成。以下是 Promise 的獨特之處:

  1. 三種狀態:Promise 可以是 待處理已履行已拒絕
  2. 不可變的狀態變化:一旦 Promise 被解決(履行或拒絕),它就無法更改狀態。
  3. 與 .then 和 .catch 連結:Promise 提供 .then() 來處理已實現的值,並提供 .catch() 來處理錯誤,使它們可組合。

Building XPromise: A Deep Dive into Custom JavaScript Promises

為什麼要建立自訂承諾?

建立自訂 Promise,如 XPromise,可以更深入地了解其內部工作原理:

  • 狀態管理:我們以確保只有一個最終狀態的方式來處理狀態。
  • 回呼隊列:Promise 必須將回呼排隊,以便在解析後執行。
  • 錯誤處理:它包括一種優雅地處理非同步錯誤的方法,模擬原生 Promise 行為。

項目演練

讓我們瀏覽一下 XPromise 的程式碼,探索使其像 JavaScript 的原生 Promises 一樣運作的每個元件。

設定狀態和基本結構

XPromise 先定義三種狀態:PENDING、FULFILLED 和 REJECTED。

const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";

class XPromise {
  constructor(executor) {
    this.state = PENDING;
    this.queue = [];
    doResolve(this, executor);
  }
  // ...
}
  1. 建構子與初始設定
    • XPromise 接受一個執行器函數,該函數會立即運作。
    • this.state 追蹤目前狀態,而 this.queue 保存透過 .then() 呼叫排隊的所有函數。

新增 then、catch 和finally 方法

透過then、catch和finally,我們處理完成、拒絕和清理場景。 XPromise 實作連結的方式如下:

const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";

class XPromise {
  constructor(executor) {
    this.state = PENDING;
    this.queue = [];
    doResolve(this, executor);
  }
  // ...
}
  1. then:then 方法建立一個新的 XPromise 實例並將其與 onFulfilled 和 onRejected 回呼一起儲存。這可確保鏈中的下一個 Promise 接收前一個 Promise 的輸出。
  2. catch:處理錯誤的簡寫,相當於呼叫 then(null, onRejected)。
  3. finally:處理無論 Promise 結果如何都會執行的清理操作。

使用句柄管理已解決的狀態

handle 函數決定 Promise 是否仍有待處理或已解決。如果它處於待處理狀態,則處理程序將添加到佇列中以供稍後執行。如果 Promise 得到解決,它會立即處理處理程序。

then(onFulfilled, onRejected) {
  const promise = new XPromise(() => {});
  handle(this, { promise, onFulfilled, onRejected });
  return promise;
}

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

finally(onFinally) {
  return this.then(onFinally, onFinally);
}

解決和拒絕承諾

履行和拒絕的 Promise 需要特殊的函數來處理其結果。 XPromise 是如何實現這一目標的:

function handle(promise, handler) {
  while (promise.state !== REJECTED && promise.value instanceof XPromise) {
    promise = promise.value;
  }

  if (promise.state === PENDING) {
    promise.queue.push(handler);
  } else {
    handleResolved(promise, handler);
  }
}
  1. 履行與拒絕

    • 履行和拒絕最終確定 Promise,更新其狀態和值。
    • 如果 value 是 Promise 或 thenable,我們會推遲 doResolve 以確保它得到正確處理。
  2. 完成排隊處理程序:

    • 一旦 Promise 解決,finale 就會遍歷佇列以依序執行所有處理程序。

執行器函數 doResolve

doResolve 函數透過包裝解析和拒絕呼叫來安全地運行執行器,防止多次呼叫它們時發生任何進一步的狀態變更。

function fulfill(promise, value) {
  if (value === promise) {
    return reject(promise, new TypeError());
  }

  if (value && (typeof value === "object" || typeof value === "function")) {
    let then;
    try {
      then = value.then;
    } catch (e) {
      return reject(promise, e);
    }

    if (typeof then === "function") {
      return doResolve(promise, then.bind(value));
    }
  }

  promise.state = FULFILLED;
  promise.value = value;
  finale(promise);
}

function reject(promise, reason) {
  promise.state = REJECTED;
  promise.value = reason;
  finale(promise);
}

XPromise 的用法範例

現在我們有了一個可以運行的 XPromise,讓我們用一個簡單的範例來嘗試:

function doResolve(promise, executor) {
  let called = false;
  function wrapFulfill(value) {
    if (called) return;
    called = true;
    fulfill(promise, value);
  }

  function wrapReject(reason) {
    if (called) return;
    called = true;
    reject(promise, reason);
  }
  try {
    executor(wrapFulfill, wrapReject);
  } catch (e) {
    wrapReject(e);
  }
}

重點

從頭開始重新實作 Promise 提供了有關如何在 JavaScript 中管理非同步程式設計的實作見解:

  • 狀態管理確保Promise僅解決一次,保持履行或拒絕。
  • 回呼隊列允許有效處理多個鍊式.then()呼叫。
  • 錯誤處理使用catch,最終有助於優雅地處理非同步錯誤。

要深入了解程式碼,請查看 GitHub 上的 XPromise 專案。試驗程式碼並隨意自訂它以探索更高級的功能,例如 Promise 競爭條件、連結和嵌套!

以上是建構 XPromise:深入研究自訂 JavaScript Promise的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn