js如何判斷變量是否為Promise Promise檢測的2種方案

要判斷一個 JavaScript 變量是否為 promise,1. 首先檢查其是否具有 then 方法,即非空且為對象,并且 obj.then 是函數;2. 更嚴格的方式是結合原生 promise 檢測與 then 方法檢測,使用 instanceof 判斷是否為原生 promise 或符合 promise/a+ 規范的對象;3. 避免使用 typeofconstructor 判斷,因其無法準確識別 promise 類型或受上下文影響導致錯誤;4. 為兼容不同 promise 庫,應僅關注 then 方法的規范性;5. 在 typescript 中可使用類型守衛 ispromise(value) 并返回 value is promise 類型,以確保類型安全并在代碼中獲得正確類型推斷。

js如何判斷變量是否為Promise Promise檢測的2種方案

判斷一個 JavaScript 變量是否為 Promise,核心在于檢測它是否具有 Promise 的必要特征:then 方法。更嚴謹地說,需要考慮變量是否遵循 Promises/A+ 規范。

js如何判斷變量是否為Promise Promise檢測的2種方案

檢測方案如下:

js如何判斷變量是否為Promise Promise檢測的2種方案

方案一:基于 then 方法的檢測

js如何判斷變量是否為Promise Promise檢測的2種方案

function isPromiseLike(obj) {   return obj !== null && typeof obj === 'Object' && typeof obj.then === 'function'; }  // 示例 const promise = new Promise((resolve, reject) => {   setTimeout(() => resolve('Resolved!'), 100); });  const notPromise = { value: 'Not a promise' };  console.log(isPromiseLike(promise)); // true console.log(isPromiseLike(notPromise)); // false

這個方法簡單直接,檢查對象是否非空、類型為 object,并且擁有一個類型為 function 的 then 屬性。 這種方法足夠應對大多數場景。

方案二:更嚴格的 Promise 實例檢測 (兼容性考慮)

function isNativePromise(obj) {   return typeof Promise !== 'undefined' && obj instanceof Promise; }  function isPromise(obj) {     return isNativePromise(obj) || isPromiseLike(obj); }  // 示例 const promise = new Promise((resolve, reject) => {   setTimeout(() => resolve('Resolved!'), 100); });  const thenable = {     then: function(resolve, reject) {         resolve('Thenable Resolved');     } };  console.log(isPromise(promise)); // true console.log(isPromise(thenable)); // true, 如果只用 isNativePromise 則會返回 false

這個方案首先檢查瀏覽器是否支持原生的 Promise 對象,如果支持,則使用 instanceof 操作符來判斷。 同時,為了兼容一些 polyfill 或者第三方 Promise 庫,還需要結合 isPromiseLike 函數,確保即使不是原生 Promise 實例,只要具有 then 方法,也能被正確識別。這種方法更全面,考慮到兼容性問題。

為什么不能簡單地使用 typeof 或 constructor 來判斷?

直接使用 typeof 無法區分 Promise 和其他對象,因為 Promise 的類型也是 object。 而 constructor 方法可能被篡改,或者在不同的 JavaScript 上下文中(例如 iframe)指向不同的 Promise 構造函數,導致判斷錯誤。 例如:

// 假設在不同的 iframe 中 const iframe = document.createElement('iframe'); document.body.appendChild(iframe); const iframeWindow = iframe.contentWindow;  const promise = new iframeWindow.Promise((resolve, reject) => {   resolve('From iframe'); });  console.log(promise.constructor === Promise); // false,因為 Promise 指向的是主窗口的 Promise 構造函數

如何處理不同 Promise 庫之間的兼容性問題?

不同的 Promise 庫(例如 Bluebird, Q)可能對 Promise 的實現細節有所不同。 為了確保兼容性,最佳實踐是使用 isPromiseLike 函數,因為它只關注 Promise 的核心特征:then 方法。 只要對象具有符合規范的 then 方法,就可以被視為 Promise,而無需關心它是由哪個庫創建的。

typescript 中如何更安全地判斷 Promise?

在 TypeScript 中,可以使用類型守衛 (Type Guard) 來更安全地判斷 Promise。 類型守衛可以確保在類型檢查階段就排除掉不符合 Promise 類型的變量,從而避免運行時錯誤。

function isPromise(obj: any): obj is Promise<any> {   return typeof obj === 'object' && obj !== null && typeof obj.then === 'function'; }  function processValue(value: any) {   if (isPromise(value)) {     // TypeScript 知道 value 是 Promise<any> 類型     value.then(result => console.log('Promise result:', result));   } else {     console.log('Not a promise:', value);   } }

通過 obj is Promise 語法,我們告訴 TypeScript,如果 isPromise 函數返回 true,那么 obj 就是一個 Promise 類型。 這樣,在 if 語句塊中,TypeScript 就能正確地推斷出 value 的類型,并提供相應的類型檢查和代碼補全。

? 版權聲明
THE END
喜歡就支持一下吧
點贊15 分享