isPromise
檢查值是否為Promise類型。
基礎用法
typescript
import { isPromise } from 'radash'
console.log(isPromise(Promise.resolve(123))) // true
console.log(isPromise(new Promise(() => {}))) // true
console.log(isPromise(Promise.reject('error'))) // true
console.log(isPromise({})) // false
console.log(isPromise([])) // false
console.log(isPromise(() => {})) // false
語法
typescript
function isPromise(value: any): value is Promise<any>
參數
value
(any): 要檢查的值
返回值
返回一個布爾值,如果值是Promise對象則返回 true
,否則返回 false
。同時作為TypeScript類型守衛。
示例
基本類型檢查
typescript
import { isPromise } from 'radash'
// Promise對象
console.log(isPromise(Promise.resolve(123))) // true
console.log(isPromise(new Promise(() => {}))) // true
console.log(isPromise(Promise.reject('error'))) // true
console.log(isPromise(Promise.all([]))) // true
console.log(isPromise(Promise.race([]))) // true
// 非Promise對象
console.log(isPromise({})) // false
console.log(isPromise([])) // false
console.log(isPromise(() => {})) // false
console.log(isPromise('hello')) // false
console.log(isPromise(123)) // false
console.log(isPromise(true)) // false
console.log(isPromise(null)) // false
console.log(isPromise(undefined)) // false
自定義Promise檢查
typescript
import { isPromise } from 'radash'
// 自定義Promise-like對象
const customPromise = {
then: (resolve: any) => resolve('custom'),
catch: () => {}
}
console.log(isPromise(customPromise)) // false
// 真正的Promise
const realPromise = Promise.resolve('real')
console.log(isPromise(realPromise)) // true
類型守衛使用
typescript
import { isPromise } from 'radash'
async function processValue(value: unknown) {
if (isPromise(value)) {
// TypeScript 知道 value 是 Promise
console.log('Processing Promise')
return await value
}
console.log('Processing non-Promise:', typeof value)
return value
}
const promise = Promise.resolve('hello')
const nonPromise = 'world'
console.log(await processValue(promise)) // Processing Promise hello
console.log(await processValue(nonPromise)) // Processing non-Promise: string world
數組過濾
typescript
import { isPromise } from 'radash'
const mixedArray = [
Promise.resolve(1),
'hello',
123,
Promise.reject('error'),
{ then: () => {} },
new Promise(() => {}),
() => {},
[]
]
const promises = mixedArray.filter(isPromise)
console.log(promises.length) // 3
const nonPromises = mixedArray.filter(item => !isPromise(item))
console.log(nonPromises.length) // 5
異步函數處理
typescript
import { isPromise } from 'radash'
function handleAsyncOperation(operation: unknown) {
if (isPromise(operation)) {
return operation.then(result => {
console.log('Promise resolved:', result)
return result
}).catch(error => {
console.log('Promise rejected:', error)
throw error
})
}
console.log('Non-Promise operation:', operation)
return Promise.resolve(operation)
}
const promiseOp = Promise.resolve('success')
const syncOp = 'immediate'
handleAsyncOperation(promiseOp) // Promise resolved: success
handleAsyncOperation(syncOp) // Non-Promise operation: immediate
API響應處理
typescript
import { isPromise } from 'radash'
interface ApiResponse {
data: unknown
error: unknown
promise: unknown
}
async function processApiResponse(response: ApiResponse) {
const processed = {
data: isPromise(response.data) ? await response.data : response.data,
error: isPromise(response.error) ? await response.error : response.error,
promise: isPromise(response.promise) ? response.promise : Promise.resolve(response.promise)
}
return processed
}
const response: ApiResponse = {
data: Promise.resolve({ id: 1, name: 'Alice' }),
error: null,
promise: 'not a promise'
}
console.log(await processApiResponse(response))
// { data: { id: 1, name: 'Alice' }, error: null, promise: Promise { 'not a promise' } }
函數包裝
typescript
import { isPromise } from 'radash'
function wrapWithPromise<T>(value: T | Promise<T>): Promise<T> {
if (isPromise(value)) {
return value
}
return Promise.resolve(value)
}
async function example() {
const syncValue = 'hello'
const asyncValue = Promise.resolve('world')
const wrapped1 = wrapWithPromise(syncValue)
const wrapped2 = wrapWithPromise(asyncValue)
console.log(await wrapped1) // hello
console.log(await wrapped2) // world
}
example()
錯誤處理
typescript
import { isPromise } from 'radash'
async function safeExecute(operation: unknown) {
try {
if (isPromise(operation)) {
return await operation
}
return operation
} catch (error) {
console.log('Error occurred:', error)
return null
}
}
const successPromise = Promise.resolve('success')
const errorPromise = Promise.reject('error')
const syncValue = 'hello'
console.log(await safeExecute(successPromise)) // success
console.log(await safeExecute(errorPromise)) // Error occurred: error null
console.log(await safeExecute(syncValue)) // hello
批量處理
typescript
import { isPromise } from 'radash'
async function processBatch(operations: unknown[]) {
const results = []
for (const operation of operations) {
if (isPromise(operation)) {
try {
const result = await operation
results.push({ success: true, data: result })
} catch (error) {
results.push({ success: false, error })
}
} else {
results.push({ success: true, data: operation })
}
}
return results
}
const batch = [
Promise.resolve('success1'),
'immediate',
Promise.reject('error1'),
Promise.resolve('success2'),
123
]
console.log(await processBatch(batch))
// [
// { success: true, data: 'success1' },
// { success: true, data: 'immediate' },
// { success: false, error: 'error1' },
// { success: true, data: 'success2' },
// { success: true, data: 123 }
// ]
條件執行
typescript
import { isPromise } from 'radash'
async function conditionalExecute(condition: unknown, operation: unknown) {
if (isPromise(condition)) {
const shouldExecute = await condition
if (shouldExecute) {
return isPromise(operation) ? await operation : operation
}
} else if (condition) {
return isPromise(operation) ? await operation : operation
}
return null
}
const trueCondition = Promise.resolve(true)
const falseCondition = Promise.resolve(false)
const syncCondition = true
const operation = Promise.resolve('executed')
console.log(await conditionalExecute(trueCondition, operation)) // executed
console.log(await conditionalExecute(falseCondition, operation)) // null
console.log(await conditionalExecute(syncCondition, operation)) // executed
超時處理
typescript
import { isPromise } from 'radash'
async function withTimeout<T>(promise: T | Promise<T>, timeoutMs: number): Promise<T> {
if (!isPromise(promise)) {
return promise
}
const timeoutPromise = new Promise<never>((_, reject) => {
setTimeout(() => reject(new Error('Timeout')), timeoutMs)
})
return Promise.race([promise, timeoutPromise])
}
const slowPromise = new Promise(resolve => {
setTimeout(() => resolve('slow result'), 2000)
})
const fastPromise = Promise.resolve('fast result')
try {
console.log(await withTimeout(slowPromise, 1000)) // Error: Timeout
} catch (error) {
console.log('Timeout occurred')
}
console.log(await withTimeout(fastPromise, 1000)) // fast result
重試機制
typescript
import { isPromise } from 'radash'
async function withRetry<T>(
operation: T | Promise<T>,
maxRetries: number = 3,
delay: number = 1000
): Promise<T> {
if (!isPromise(operation)) {
return operation
}
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation
} catch (error) {
if (attempt === maxRetries) {
throw error
}
await new Promise(resolve => setTimeout(resolve, delay))
}
}
throw new Error('Max retries exceeded')
}
const failingPromise = new Promise((_, reject) => {
setTimeout(() => reject('Failed'), 100)
})
const successPromise = Promise.resolve('Success')
try {
console.log(await withRetry(successPromise)) // Success
console.log(await withRetry(failingPromise, 3, 100)) // Error after 3 attempts
} catch (error) {
console.log('All retries failed:', error)
}
緩存機制
typescript
import { isPromise } from 'radash'
class PromiseCache {
private cache = new Map<string, Promise<any>>()
async getOrCreate<T>(
key: string,
factory: () => T | Promise<T>
): Promise<T> {
if (this.cache.has(key)) {
return this.cache.get(key)!
}
const promise = factory()
if (isPromise(promise)) {
this.cache.set(key, promise)
return promise
}
const resolvedPromise = Promise.resolve(promise)
this.cache.set(key, resolvedPromise)
return resolvedPromise
}
clear() {
this.cache.clear()
}
}
const cache = new PromiseCache()
async function expensiveOperation(id: string) {
console.log(`Executing expensive operation for ${id}`)
await new Promise(resolve => setTimeout(resolve, 1000))
return `Result for ${id}`
}
// 第一次調用會執行操作
console.log(await cache.getOrCreate('user1', () => expensiveOperation('user1')))
// 第二次調用會使用緩存
console.log(await cache.getOrCreate('user1', () => expensiveOperation('user1')))
並發控制
typescript
import { isPromise } from 'radash'
class ConcurrencyLimiter {
private running = 0
private queue: Array<() => Promise<any>> = []
constructor(private maxConcurrency: number) {}
async execute<T>(operation: T | Promise<T>): Promise<T> {
if (!isPromise(operation)) {
return operation
}
if (this.running >= this.maxConcurrency) {
return new Promise((resolve, reject) => {
this.queue.push(async () => {
try {
const result = await operation
resolve(result)
} catch (error) {
reject(error)
}
})
})
}
this.running++
try {
const result = await operation
return result
} finally {
this.running--
if (this.queue.length > 0) {
const next = this.queue.shift()!
next()
}
}
}
}
const limiter = new ConcurrencyLimiter(2)
async function simulateWork(id: number) {
console.log(`Starting work ${id}`)
await new Promise(resolve => setTimeout(resolve, 1000))
console.log(`Completed work ${id}`)
return `Result ${id}`
}
// 並發執行,但最多同時運行2個
const promises = Array.from({ length: 5 }, (_, i) =>
limiter.execute(simulateWork(i + 1))
)
console.log(await Promise.all(promises))
事件處理
typescript
import { isPromise } from 'radash'
class EventHandler {
private handlers: Array<(...args: any[]) => any | Promise<any>> = []
addHandler(handler: (...args: any[]) => any | Promise<any>) {
this.handlers.push(handler)
}
async emit(...args: any[]) {
const results = []
for (const handler of this.handlers) {
const result = handler(...args)
if (isPromise(result)) {
try {
results.push(await result)
} catch (error) {
results.push({ error })
}
} else {
results.push(result)
}
}
return results
}
}
const eventHandler = new EventHandler()
eventHandler.addHandler((data) => {
console.log('Sync handler:', data)
return 'sync result'
})
eventHandler.addHandler(async (data) => {
console.log('Async handler:', data)
await new Promise(resolve => setTimeout(resolve, 100))
return 'async result'
})
eventHandler.emit('test data').then(results => {
console.log('All handlers completed:', results)
})
性能測試
typescript
import { isPromise } from 'radash'
function benchmarkIsPromise() {
const testValues = [
Promise.resolve(1),
Promise.reject('error'),
new Promise(() => {}),
{},
[],
() => {},
'hello',
123,
true,
null,
undefined
]
const iterations = 1000000
const start = performance.now()
for (let i = 0; i < iterations; i++) {
testValues.forEach(value => {
isPromise(value)
})
}
const end = performance.now()
console.log(`Benchmark completed in ${end - start}ms`)
}
// benchmarkIsPromise() // 運行性能測試
注意事項
- Promise檢測: 准確檢測真正的Promise對象
- 類型守衛: 作為TypeScript類型守衛使用
- 性能: 檢查速度很快,適合高頻使用
- 邊界值: 正確處理所有邊界情況
- 自定義Promise: 不檢測Promise-like對象
與其他方法的區別
isPromise()
: 檢查是否為Promise對象value instanceof Promise
: 原生JavaScript檢查typeof value === 'object' && value !== null && typeof value.then === 'function'
: 手動檢查value && typeof value.then === 'function'
: 簡單但不夠准確
實際應用場景
- 異步處理: 處理可能返回Promise的函數
- API調用: 處理異步API響應
- 錯誤處理: 統一處理同步和異步錯誤
- 緩存機制: 緩存Promise結果
- 並發控制: 限制並發Promise數量
- 事件處理: 處理異步事件處理器