寫在前面
tips:點贊 + 收藏 = 學會!
- 我們前面已經介紹了
radash
的相關資訊和所有Array
相關方法,詳情可前往主頁檢視。 - 本篇我們繼續介紹radash中非同步相關的方法。
- 所有方法分享完畢後,後續作者也會整理出
Radash
庫所有方法的使用目錄,包括文章說明和腦圖說明。- 因為方法較多,後續將專門釋出一篇總結文件,方便大家查閱使用。
- 所有方法的思維導圖說明後續也會上傳至 github 和 gitee,有需要的可以訪問下載。
all:同時執行多個非同步操作
- 使用說明
- 功能描述: 類似於
Promise.all
和Promise.allSettled
,等待一個由多個Promise
組成的物件或陣列中的所有Promise
都完成(或者其中一個失敗)。執行的所有錯誤和丟擲的錯誤都會收集在AggregateError
中。 - 引數:promise物件/promise陣列
- 返回值:所有
promise
執行後的結果陣列或物件
- 功能描述: 類似於
- 使用程式碼示例
import { all } from 'radash' // 傳入promise陣列 const [user] = await all([ api.users.create(...), s3.buckets.create(...), slack.customerSuccessChannel.sendMessage(...) ]) // 傳入物件 const { user } = await all({ user: api.users.create(...), bucket: s3.buckets.create(...), message: slack.customerSuccessChannel.sendMessage(...) })
- 原始碼解析
// 定義一個泛型非同步函式 `all`。 export async function all< // 泛型約束 `T` 可以是一個 `Promise` 陣列或一個 `Promise` 物件。 T extends Record<string, Promise<any>> | Promise<any>[] >(promises: T) { // 根據 `promises` 是陣列還是物件,將其轉換成一個統一格式的陣列 `entries`。 const entries = isArray(promises) ? promises.map(p => [null, p] as [null, Promise<any>]) : Object.entries(promises) // 使用 `Promise.all` 等待所有 `Promise` 完成,並處理每個 `Promise` 的結果和異常。 const results = await Promise.all( entries.map(([key, value]) => value .then(result => ({ result, exc: null, key })) // 如果成功,記錄結果。 .catch(exc => ({ result: null, exc, key })) // 如果失敗,記錄異常。 ) ) // 篩選出所有出現異常的結果。 const exceptions = results.filter(r => r.exc) // 如果有異常,丟擲一個 `AggregateError`,包含所有異常。 if (exceptions.length > 0) { throw new AggregateError(exceptions.map(e => e.exc)) } // 如果輸入的 `promises` 是陣列,返回一個包含所有結果的陣列。 if (isArray(promises)) { return results.map(r => r.result) as T extends Promise<any>[] ? PromiseValues<T> : unknown } // 如果輸入的 `promises` 是物件,將結果組合成一個新物件並返回。 return results.reduce( (acc, item) => ({ ...acc, [item.key!]: item.result // 使用斷言 `item.key!`,因為我們知道 `key` 不會是 `null`。 }), {} as { [K in keyof T]: Awaited<T[K]> } // 返回型別是一個物件,其鍵型別為 `T` 的鍵,值型別為 `T` 中 `Promise` 解析後的型別。 ) }
- 方法流程說明:
- 將輸入的
promises
轉換為一個統一格式的entries
陣列,無論它是一個Promise
陣列還是一個Promise
物件。 - 對於每個
entry
,建立一個新的Promise
來處理成功和失敗的情況,並使用Promise.all
等待所有這些新Promise
完成。 - 如果所有
Promise
都成功解析,根據promises
是陣列還是物件,返回一個包含所有結果的陣列或物件。 - 如果有一個或多個
Promise
失敗,則丟擲一個AggregateError
,其中包含所有失敗的Promise
的異常。
- 將輸入的
- 方法流程說明:
defer:在非同步流程中新增清理或錯誤處理邏輯
- 使用說明
- 功能描述:用來執行一個非同步函式,同時提供註冊回撥的機制,在非同步函式執行完成後執行特定回撥操作。
- 引數:非同步函式。
- 返回值:非同步函式成功執行時,返回其響應結果,否則重新丟擲錯誤。
- 使用程式碼示例
import { defer } from 'radash' await defer(async (cleanup) => { const buildDir = await createBuildDir() cleanup(() => fs.unlink(buildDir)) await build() }) await defer(async (register) => { const org = await api.org.create() register(async () => api.org.delete(org.id), { rethrow: true }) const user = await api.user.create() register(async () => api.users.delete(user.id), { rethrow: true }) await executeTest(org, user) })
- 原始碼解析
// 定義一個非同步泛型函式 `defer`。 export const defer = async <TResponse>( // `func` 是一個接受註冊函式 `register` 的非同步函式。 func: ( register: ( // `register` 允許 `func` 註冊一個回撥函式 `fn`,該函式在 `func` 執行完成後呼叫。 // 可以透過 `options` 指定是否在回撥函式中重新丟擲錯誤。 fn: (error?: any) => any, options?: { rethrow?: boolean } ) => void ) => Promise<TResponse> ): Promise<TResponse> => { // 初始化一個用於存放回撥函式及其選項的陣列 `callbacks`。 const callbacks: { fn: (error?: any) => any rethrow: boolean }[] = [] // 實現註冊函式 `register`,它將回撥函式及其選項新增到 `callbacks` 陣列。 const register = ( fn: (error?: any) => any, options?: { rethrow?: boolean } ) => callbacks.push({ fn, rethrow: options?.rethrow ?? false }) // 呼叫 `tryit` 函式執行 `func`,並傳入 `register`。 // `tryit` 函式不在提供的程式碼片段中,但我們可以假設它是一個錯誤處理函式,返回一個包含錯誤和響應的元組。 const [err, response] = await tryit(func)(register) // 遍歷 `callbacks` 陣列,依次執行每個回撥函式。 for (const { fn, rethrow } of callbacks) { // 使用 `tryit` 函式呼叫回撥,以捕獲並處理任何丟擲的錯誤。 const [rethrown] = await tryit(fn)(err) // 如果回撥函式中有錯誤被重新丟擲,並且 `rethrow` 選項為 `true`,則重新丟擲該錯誤。 if (rethrown && rethrow) throw rethrown } // 如果 `func` 執行時有錯誤產生,重新丟擲該錯誤。 if (err) throw err // 如果 `func` 執行成功,返回響應結果。 return response }
- 方法流程說明:
- 定義一個
callbacks
陣列來儲存註冊的回撥函式及其選項。 - 實現
register
函式,該函式允許func
註冊回撥函式和選項。 - 呼叫外部提供的(但在程式碼片段中未定義)
tryit
函式執行func
,並傳遞register
函式給func
。 - 等待
func
完成執行,獲取可能的錯誤err
和響應response
。 - 依次執行
callbacks
陣列中的回撥函式,處理可能的錯誤。 - 如果任何一個回撥函式中出現需要重新丟擲的錯誤,並且其
rethrow
選項為true
,則重新丟擲該錯誤。 - 如果
func
執行時產生了錯誤,重新丟擲該錯誤。 - 如果
func
成功執行,返回其響應結果。
- 定義一個
- 方法流程說明:
guard:執行一個函式,並提供錯誤處理的能力
- 使用說明
- 功能描述:
guard
函式可以用來為函式呼叫提供額外的錯誤處理邏輯,特別是當你希望根據錯誤型別選擇性地處理錯誤時。 - 引數:目標函式、指定錯誤物件得函式(可選)。
- 返回值:丟擲原始或返回undefined。
- 功能描述:
- 使用程式碼示例
import { guard } from 'radash' const users = (await guard(fetchUsers)) ?? [] const isInvalidUserError = (err: any) => err.code === 'INVALID_ID' const user = (await guard(fetchUser, isInvalidUserError)) ?? DEFAULT_USER
- 原始碼解析
// 定義一個泛型函式 `guard`。 export const guard = <TFunction extends () => any>( // 引數 `func` 是一個無引數的函式,它可能返回任何型別的值,包括 `Promise`。 func: TFunction, // 可選引數 `shouldGuard` 是一個函式,它接受一個錯誤物件 `err`, // 並返回一個布林值,指示是否應該 "guard" 這個錯誤。 shouldGuard?: (err: any) => boolean // 函式的返回型別依賴於 `func` 的返回型別。如果 `func` 返回一個 `Promise`, // 則 `guard` 返回一個 `Promise`,該 `Promise` 解析為 `func` 的返回值或 `undefined`。 // 如果 `func` 不返回 `Promise`,則 `guard` 返回 `func` 的返回值或 `undefined`。 ): ReturnType<TFunction> extends Promise<any> ? Promise<Awaited<ReturnType<TFunction>> | undefined> : ReturnType<TFunction> | undefined => { // 定義一個內部函式 `_guard`,它接受一個錯誤物件 `err`。 const _guard = (err: any) => { // 如果提供了 `shouldGuard` 函式並且該函式返回 `false`, // 表示不應該 "guard" 這個錯誤,則重新丟擲該錯誤。 if (shouldGuard && !shouldGuard(err)) throw err // 否則,返回 `undefined`。 return undefined as any } // 定義一個型別守衛函式 `isPromise`,它檢查一個值是否為 `Promise`。 const isPromise = (result: any): result is Promise<any> => result instanceof Promise try { // 嘗試執行 `func` 並獲取結果。 const result = func() // 如果 `result` 是一個 `Promise`,使用 `catch` 方法應用 `_guard` 函式。 // 否則,直接返回 `result`。 return isPromise(result) ? result.catch(_guard) : result } catch (err) { // 如果在執行 `func` 時丟擲錯誤,使用 `_guard` 函式處理該錯誤。 return _guard(err) } }
- 方法流程說明:
- 嘗試執行
func
函式並捕獲任何丟擲的錯誤。 - 如果
func
執行成功並返回一個Promise
,那麼使用catch
方法捕獲該Promise
可能丟擲的錯誤,並應用_guard
函式。 - 如果
func
執行成功並沒有返回Promise
,那麼直接返回結果。 - 如果
func
丟擲錯誤,應用_guard
函式來決定是否重新丟擲錯誤或返回undefined
。 - 如果提供了
shouldGuard
函式,它將用來判斷是否應該 "guard"(捕獲並返回undefined
)錯誤。如果shouldGuard
函式返回false
,則丟擲原始錯誤;如果返回true
或未提供shouldGuard
函式,則返回undefined
。
- 嘗試執行
- 方法流程說明:
map:對一個陣列中的每個元素執行一個非同步對映函式
- 使用說明
- 功能描述:它用於對一個陣列中的每個元素執行一個非同步對映函式,並返回一個包含所有對映結果的新陣列。這個函式是
Array.prototype.map
方法的非同步版本。 - 引數:陣列,非同步函式。
- 返回值:對映後的新陣列。
- 功能描述:它用於對一個陣列中的每個元素執行一個非同步對映函式,並返回一個包含所有對映結果的新陣列。這個函式是
- 使用程式碼示例
import { map } from 'radash' const userIds = [1, 2, 3, 4] const users = await map(userIds, async (userId) => { return await api.users.find(userId) })
- 原始碼解析
// 定義一個非同步函式 `map`。 export const map = async <T, K>( // 第一個引數 `array` 是一個具有隻讀屬性的泛型陣列。 array: readonly T[], // 第二個引數 `asyncMapFunc` 是一個非同步對映函式,它接受一個陣列元素和它的索引, // 返回一個 `Promise`,該 `Promise` 解析為新型別 `K` 的值。 asyncMapFunc: (item: T, index: number) => Promise<K> ): Promise<K[]> => { // 如果傳入的陣列 `array` 不存在,則返回一個空陣列。 if (!array) return [] // 初始化一個空陣列 `result`,用於存放對映後的新值。 let result = [] // 初始化一個索引計數器 `index`。 let index = 0 // 使用 `for...of` 迴圈遍歷陣列 `array` 的每個元素。 for (const value of array) { // 對每個元素呼叫 `asyncMapFunc` 對映函式,並等待其 `Promise` 解析。 const newValue = await asyncMapFunc(value, index++) // 將解析後的新值新增到 `result` 陣列中。 result.push(newValue) } // 迴圈完成後,返回包含所有新值的陣列 `result`。 return result }
- 方法流程說明:
- 檢查
array
是否存在。如果不存在,返回一個空陣列。 - 初始化一個空陣列
result
用於儲存對映結果,以及一個索引計數器index
。 - 遍歷
array
中的每個元素。 - 對於每個元素,呼叫非同步對映函式
asyncMapFunc
並等待Promise
解析。 - 將非同步對映函式解析後的結果新增到
result
陣列中。 - 在遍歷完所有元素之後,返回包含所有對映結果的
result
陣列。
- 檢查
- 方法流程說明:
parallel:並行地處理陣列中的元素,並對每個元素執行一個非同步函式
- 使用說明
- 功能描述:這個函式會限制同時進行的非同步操作的數量,以避免同時啟動過多的非同步任務。
- 引數:限制數量(number)、需要被非同步處理的元素陣列、轉換函式(將陣列中的每個元素轉換為一個非同步操作)。
- 返回值:返回一個陣列,該陣列包含了按原陣列順序排序的所有成功的結果。
- 使用程式碼示例
// 定義一個非同步泛型函式 `parallel`。 export const parallel = async <T, K>( // `limit` 是一個數字,指定了可以同時執行的非同步任務的最大數量。 limit: number, // `array` 是一個只讀陣列,包含將要被非同步處理的元素。 array: readonly T[], // `func` 是一個函式,將陣列中的每個元素轉換為一個非同步操作(返回 Promise)。 func: (item: T) => Promise<K> ): Promise<K[]> => { // 將陣列 `array` 轉換為包含元素和它們索引的物件的陣列 `work`。 const work = array.map((item, index) => ({ index, item })) // 定義一個處理函式 `processor`,它將非同步處理 `work` 陣列中的元素。 const processor = async (res: (value: WorkItemResult<K>[]) => void) => { const results: WorkItemResult<K>[] = [] while (true) { // 從 `work` 陣列的末尾取出一個元素進行處理。 const next = work.pop() // 如果沒有更多元素,呼叫回撥函式 `res` 並傳入結果陣列 `results`。 if (!next) return res(results) // 使用 `tryit` 函式執行 `func` 並處理結果或錯誤。 const [error, result] = await tryit(func)(next.item) // 將結果或錯誤新增到 `results` 陣列中。 results.push({ error, result: result as K, index: next.index }) } } // 建立一個 `queues` 陣列,它包含了 `limit` 個新的 Promise,每個 Promise 都由 `processor` 函式處理。 const queues = list(1, limit).map(() => new Promise(processor)) // 使用 `Promise.all` 等待所有的 `queues` 中的 Promise 完成。 const itemResults = (await Promise.all(queues)) as WorkItemResult<K>[][] // 將所有的結果扁平化並根據索引排序,然後使用 `fork` 函式將結果分為錯誤和成功的結果。 const [errors, results] = fork( sort(itemResults.flat(), r => r.index), x => !!x.error ) // 如果有任何錯誤,丟擲一個 `AggregateError` 包含所有錯誤。 if (errors.length > 0) { throw new AggregateError(errors.map(error => error.error)) } // 返回一個陣列,它包含了按原陣列順序排序的所有成功的結果。 return results.map(r => r.result) }
- 原始碼解析
// 定義一個非同步泛型函式 `parallel`。 export const parallel = async <T, K>( // `limit` 是一個數字,指定了可以同時執行的非同步任務的最大數量。 limit: number, // `array` 是一個只讀陣列,包含將要被非同步處理的元素。 array: readonly T[], // `func` 是一個函式,將陣列中的每個元素轉換為一個非同步操作(返回 Promise)。 func: (item: T) => Promise<K> ): Promise<K[]> => { // 將陣列 `array` 轉換為包含元素和它們索引的物件的陣列 `work`。 const work = array.map((item, index) => ({ index, item })) // 定義一個處理函式 `processor`,它將非同步處理 `work` 陣列中的元素。 const processor = async (res: (value: WorkItemResult<K>[]) => void) => { const results: WorkItemResult<K>[] = [] while (true) { // 從 `work` 陣列的末尾取出一個元素進行處理。 const next = work.pop() // 如果沒有更多元素,呼叫回撥函式 `res` 並傳入結果陣列 `results`。 if (!next) return res(results) // 使用 `tryit` 函式執行 `func` 並處理結果或錯誤。 const [error, result] = await tryit(func)(next.item) // 將結果或錯誤新增到 `results` 陣列中。 results.push({ error, result: result as K, index: next.index }) } } // 建立一個 `queues` 陣列,它包含了 `limit` 個新的 Promise,每個 Promise 都由 `processor` 函式處理。 const queues = list(1, limit).map(() => new Promise(processor)) // 使用 `Promise.all` 等待所有的 `queues` 中的 Promise 完成。 const itemResults = (await Promise.all(queues)) as WorkItemResult<K>[][] // 將所有的結果扁平化並根據索引排序,然後使用 `fork` 函式將結果分為錯誤和成功的結果。 const [errors, results] = fork( sort(itemResults.flat(), r => r.index), x => !!x.error ) // 如果有任何錯誤,丟擲一個 `AggregateError` 包含所有錯誤。 if (errors.length > 0) { throw new AggregateError(errors.map(error => error.error)) } // 返回一個陣列,它包含了按原陣列順序排序的所有成功的結果。 return results.map(r => r.result) }
- 這段程式碼中使用了幾個未定義的函式和型別,如
tryit
、list
、fork
和sort
,以及型別WorkItemResult<K>
。我們可以假設這些函式和型別具有以下功能:tryit(func)(item)
:執行func(item)
並捕獲任何丟擲的錯誤,返回一個包含錯誤和結果的元組。list(1, limit)
:建立一個包含從 1 到limit
的數字的陣列。fork(array, condition)
:分割陣列array
,根據condition
函式返回的布林值將陣列分為包含錯誤的元素和成功的元素兩個陣列。sort(array, keySelector)
:根據keySelector
函式返回的鍵對陣列array
進行排序。WorkItemResult<K>
:一個型別,表示工作項的結果,包含可能的error
、成功的result
以及元素的index
。
- 這段程式碼中使用了幾個未定義的函式和型別,如
reduce:對陣列中的每個元素執行一個非同步歸約函式
- 使用說明
- 功能描述:它是
Array.prototype.reduce
方法的非同步版本,用於對陣列中的每個元素執行一個非同步歸約函式,並返回最終的歸約值。 - 引數:被歸約處理的元素陣列、非同步歸約函式。
- 返回值:返回最終歸約的值。
- 功能描述:它是
- 使用程式碼示例
import { reduce } from 'radash' const userIds = [1, 2, 3, 4] const users = await reduce(userIds, async (acc, userId) => { const user = await api.users.find(userId) return { ...acc, [userId]: user } }, {})
- 原始碼解析
// 定義一個非同步泛型函式 `reduce`。 export const reduce = async <T, K>( // 第一個引數 `array` 是一個只讀陣列,包含將要被歸約處理的元素。 array: readonly T[], // 第二個引數 `asyncReducer` 是一個非同步歸約函式,它接受累加值 `acc`、當前元素 `item` 和它的索引 `index`, // 並返回一個 `Promise`,該 `Promise` 解析為新的累加值。 asyncReducer: (acc: K, item: T, index: number) => Promise<K>, // 第三個引數 `initValue` 是可選的初始值。 initValue?: K ): Promise<K> => { // 檢查初始值是否提供了。 const initProvided = initValue !== undefined // 如果沒有提供初始值且陣列為空,則丟擲錯誤。 if (!initProvided && array?.length < 1) { throw new Error('Cannot reduce empty array with no init value') } // 如果提供了初始值,使用整個陣列;否則,從陣列的第二個元素開始迭代。 const iter = initProvided ? array : array.slice(1) // 初始化累加值 `value`。如果提供了初始值,使用它;否則使用陣列的第一個元素。 let value: any = initProvided ? initValue : array[0] // 使用 `for...of` 迴圈和 `entries` 方法遍歷陣列或其子陣列。 for (const [i, item] of iter.entries()) { // 對每個元素呼叫非同步歸約函式 `asyncReducer` 並等待其 `Promise` 解析。 value = await asyncReducer(value, item, i) } // 迴圈完成後,返回最終的累加值 `value`。 return value }
- 方法流程說明:
- 檢查是否提供了初始值
initValue
。 - 如果沒有提供初始值且陣列為空,則丟擲錯誤,因為無法從空陣列中歸約出一個值。
- 確定迭代的陣列。如果提供了初始值,則迭代整個陣列;如果沒有提供初始值,則從陣列的第二個元素開始迭代。
- 初始化累加值
value
。如果提供了初始值,則使用該初始值;如果沒有提供初始值,則使用陣列的第一個元素作為初始累加值。 - 遍歷陣列,對每個元素呼叫非同步歸約函式
asyncReducer
,並等待其返回的Promise
解析。 - 更新累加值
value
為asyncReducer
返回的新值。 - 在遍歷完所有元素之後,返回最終的累加值。
- 檢查是否提供了初始值
- 方法流程說明:
retry:反覆嘗試執行一個非同步操作,直到達到設定上限
- 使用說明
- 功能描述:用於反覆嘗試執行一個非同步操作,直到成功或達到重試次數上限。如果操作失敗,可以選擇在重試之間設定延遲或使用退避函式(backoff)來計算延遲時間。
- 引數:條件物件options(包含:重複次數、延遲、退避函式)、失敗執行的非同步操作函式。
- 返回值:可能發揮undefined。
- 使用程式碼示例
import { retry } from 'radash' await retry({}, api.users.list) await retry({ times: 10 }, api.users.list) await retry({ times: 2, delay: 1000 }, api.users.list) // exponential backoff await retry({ backoff: i => 10**i }, api.users.list)
- 原始碼解析
// 定義一個非同步泛型函式 `retry`。 export const retry = async <TResponse>( // `options` 物件包含重試策略的選項。 options: { times?: number // 重試次數,預設為 3。 delay?: number | null // 固定延遲時間,如果提供,則在重試之間等待這麼多毫秒。 backoff?: (count: number) => number // 退避函式,可以根據重試次數來計算延遲時間。 }, // `func` 是要執行的非同步函式,它可能會失敗。 func: (exit: (err: any) => void) => Promise<TResponse> ): Promise<TResponse> => { // 從 `options` 中獲取重試次數、固定延遲時間和退避函式。 const times = options?.times ?? 3 const delay = options?.delay const backoff = options?.backoff ?? null // 使用 `range` 函式生成一個序列,並遍歷這個序列進行重試。 for (const i of range(1, times)) { // 嘗試執行 `func` 函式,並捕獲可能的錯誤 `err` 和結果 `result`。 const [err, result] = (await tryit(func)((err: any) => { // 如果 `func` 失敗,並使用 `exit` 函式退出,則丟擲一個特殊的錯誤物件。 throw { _exited: err } })) as [any, TResponse] // 如果沒有錯誤,說明 `func` 成功執行,返回結果。 if (!err) return result // 如果有特殊的退出錯誤,重新丟擲原始錯誤。 if (err._exited) throw err._exited // 如果是最後一次重試且仍然失敗,丟擲錯誤。 if (i === times) throw err // 如果設定了固定延遲時間,使用 `sleep` 函式等待。 if (delay) await sleep(delay) // 如果提供了退避函式,根據重試次數計算延遲時間並等待。 if (backoff) await sleep(backoff(i)) } // 如果程式碼執行到這裡,說明邏輯上不應該到達的程式碼路徑。 // 這是為了滿足 TypeScript 的嚴格模式要求。 /* istanbul ignore next */ return undefined as unknown as TResponse }
- 方法流程說明:
- 從
options
中獲取重試次數、延遲和退避函式。 - 遍歷從 1 到重試次數的範圍。
- 在每次迭代中,嘗試執行
func
並捕獲可能的錯誤和結果。 - 如果
func
成功執行(沒有錯誤),返回結果。 - 如果有錯誤,並且是透過
exit
函式顯式退出的,重新丟擲原始錯誤。 - 如果達到了重試次數上限並且仍然失敗,丟擲最後一次的錯誤。
- 如果指定了延遲或退避函式,根據相應的策略等待一段時間後再重試。
- 如果執行到函式的末尾,返回
undefined
作為佔位符,因為邏輯上不應該到達這裡。
- 從
- 方法流程說明:
sleep:提供一個延時機制
- 使用說明
- 功能描述:提供一個延時機制,通常用於非同步操作中的暫停。
- 引數:暫停時間(ms)。
- 返回值:返回一個新的Promise。
- 使用程式碼示例
import { sleep } from 'radash' await sleep(2000) // => waits 2 seconds
- 原始碼解析
// 定義一個名為 `sleep` 的函式。 export const sleep = (milliseconds: number) => { // 返回一個新的 Promise。 return new Promise(res => // 使用 `setTimeout` 函式設定一個定時器,它在 `milliseconds` 指定的毫秒數後執行。 setTimeout( // 當定時器到時,呼叫 `res` 函式來解析這個 Promise。 res, // 傳遞給 `setTimeout` 的毫秒數,它決定了延時的長度。 milliseconds ) ) }
- 方法流程說明:當你呼叫
sleep
函式並傳入一個毫秒數時,它會返回一個Promise
。這個Promise
不會立即解析,而是會等待你指定的時間長度。當時間到了之後,Promise
會被解析,然後你可以在.then()
方法中繼續執行後續的程式碼,或者你可以在async
函式中使用await
關鍵字來等待Promise
解析。
- 方法流程說明:當你呼叫
tryit:捕獲函式在執行過程中可能丟擲的同步或非同步錯誤
- 使用說明
- 功能描述:
tryit
是一個高階函式。用於捕獲函式在執行過程中可能丟擲的同步或非同步錯誤,並返回一個元組,其中包含錯誤物件或函式的返回值。這個函式的目的是提供一種安全執行任意函式並處理錯誤的方式。 - 引數:需要被捕獲的函式。
- 返回值:返回一個新函式,該函式接收與傳入函式相同的引數。
- 功能描述:
- 使用程式碼示例
import { tryit } from 'radash' const findUser = tryit(api.users.find) const [err, user] = await findUser(userId)
- 原始碼解析
// 定義一個泛型高階函式 `tryit`。 export const tryit = <Args extends any[], Return>( // `func` 是一個接受任意引數的函式,其返回值可以是任何型別,包括 `Promise`。 func: (...args: Args) => Return ) => { // 返回一個新函式,這個新函式接受與 `func` 相同的引數。 return ( ...args: Args // 新函式的返回型別取決於 `func` 的返回型別是否是 `Promise`。 // 如果 `func` 返回 `Promise`,則返回一個 `Promise`,包含一個錯誤或函式返回值的元組。 // 如果 `func` 返回非 `Promise`,則直接返回錯誤或函式返回值的元組。 ): Return extends Promise<any> ? Promise<[Error, undefined] | [undefined, Awaited<Return>]> : [Error, undefined] | [undefined, Return] => { try { // 嘗試執行 `func` 並獲取結果。 const result = func(...args) // 使用輔助函式 `isPromise` 檢查 `result` 是否是 `Promise`。 if (isPromise(result)) { // 如果是 `Promise`,使用 `then` 和 `catch` 方法處理結果或捕獲錯誤。 return result .then(value => [undefined, value]) // 成功時返回值的元組。 .catch(err => [err, undefined]) // 錯誤時返回錯誤的元組。 } // 如果 `result` 不是 `Promise`,直接返回值的元組。 return [undefined, result] } catch (err) { // 如果執行 `func` 時捕獲到同步錯誤,返回錯誤的元組。 return [err as any, undefined] } } }
- 方法流程說明:
tryit
函式接受一個函式func
作為引數。tryit
返回一個新函式,這個新函式接受與func
相同的引數。- 當呼叫這個新函式時,它嘗試執行
func
。 - 如果
func
成功執行,且其返回值不是Promise
,新函式返回一個元組[undefined, result]
。 - 如果
func
返回一個Promise
,新函式返回一個Promise
,該Promise
解析為元組[undefined, value]
或[err, undefined]
,具體取決於Promise
是成功解析還是被拒絕。 - 如果在執行
func
時捕獲到同步錯誤,新函式返回一個元組[err, undefined]
。 - 如果
func
的返回型別是Promise
,那麼新函式的返回型別也是Promise
,否則返回型別就是元組。
- 方法流程說明:
寫在後面
- 後續我們會繼續分享
Radash
庫中其他方法的使用和原始碼解析。 - 大家有任何問題或見解,歡迎評論區留言交流和批評指正!!!
- 你的每一個點贊和收藏都是作者寫作的動力!!!
- 點選訪問:radash官網