@tamagui/use-async 1.128.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/cjs/errors.cjs +30 -0
- package/dist/cjs/errors.js +25 -0
- package/dist/cjs/errors.js.map +6 -0
- package/dist/cjs/errors.native.js +124 -0
- package/dist/cjs/errors.native.js.map +6 -0
- package/dist/cjs/idle.cjs +38 -0
- package/dist/cjs/idle.js +34 -0
- package/dist/cjs/idle.js.map +6 -0
- package/dist/cjs/idle.native.js +45 -0
- package/dist/cjs/idle.native.js.map +6 -0
- package/dist/cjs/index.cjs +21 -0
- package/dist/cjs/index.js +18 -0
- package/dist/cjs/index.js.map +6 -0
- package/dist/cjs/index.native.js +26 -0
- package/dist/cjs/index.native.js.map +6 -0
- package/dist/cjs/sleep.cjs +29 -0
- package/dist/cjs/sleep.js +25 -0
- package/dist/cjs/sleep.js.map +6 -0
- package/dist/cjs/sleep.native.js +31 -0
- package/dist/cjs/sleep.native.js.map +6 -0
- package/dist/cjs/useAsyncEffect.cjs +61 -0
- package/dist/cjs/useAsyncEffect.js +56 -0
- package/dist/cjs/useAsyncEffect.js.map +6 -0
- package/dist/cjs/useAsyncEffect.native.js +65 -0
- package/dist/cjs/useAsyncEffect.native.js.map +6 -0
- package/dist/esm/errors.js +9 -0
- package/dist/esm/errors.js.map +6 -0
- package/dist/esm/errors.mjs +7 -0
- package/dist/esm/errors.mjs.map +1 -0
- package/dist/esm/errors.native.js +94 -0
- package/dist/esm/errors.native.js.map +1 -0
- package/dist/esm/idle.js +18 -0
- package/dist/esm/idle.js.map +6 -0
- package/dist/esm/idle.mjs +14 -0
- package/dist/esm/idle.mjs.map +1 -0
- package/dist/esm/idle.native.js +21 -0
- package/dist/esm/idle.native.js.map +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +6 -0
- package/dist/esm/index.mjs +5 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/index.native.js +5 -0
- package/dist/esm/index.native.js.map +1 -0
- package/dist/esm/sleep.js +9 -0
- package/dist/esm/sleep.js.map +6 -0
- package/dist/esm/sleep.mjs +6 -0
- package/dist/esm/sleep.mjs.map +1 -0
- package/dist/esm/sleep.native.js +8 -0
- package/dist/esm/sleep.native.js.map +1 -0
- package/dist/esm/useAsyncEffect.js +41 -0
- package/dist/esm/useAsyncEffect.js.map +6 -0
- package/dist/esm/useAsyncEffect.mjs +36 -0
- package/dist/esm/useAsyncEffect.mjs.map +1 -0
- package/dist/esm/useAsyncEffect.native.js +39 -0
- package/dist/esm/useAsyncEffect.native.js.map +1 -0
- package/package.json +43 -0
- package/src/errors.ts +6 -0
- package/src/idle.ts +32 -0
- package/src/index.ts +4 -0
- package/src/sleep.ts +8 -0
- package/src/useAsyncEffect.ts +73 -0
package/src/idle.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AbortError } from './errors'
|
|
2
|
+
|
|
3
|
+
const idleCb: Function =
|
|
4
|
+
typeof requestIdleCallback === 'undefined'
|
|
5
|
+
? (cb: Function) => setTimeout(cb, 1)
|
|
6
|
+
: requestIdleCallback
|
|
7
|
+
|
|
8
|
+
export const idle = async (signal?: AbortSignal): Promise<void> => {
|
|
9
|
+
await new Promise((res) => idleCb(res))
|
|
10
|
+
if (signal?.aborted) {
|
|
11
|
+
throw new AbortError()
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const fullyIdle = async (signal?: AbortSignal): Promise<void> => {
|
|
16
|
+
while (true) {
|
|
17
|
+
const startTime = Date.now()
|
|
18
|
+
await idle(signal)
|
|
19
|
+
const endTime = Date.now()
|
|
20
|
+
const duration = endTime - startTime
|
|
21
|
+
|
|
22
|
+
// If idle callback took less than 15ms, consider it truly idle
|
|
23
|
+
if (duration < 15) {
|
|
24
|
+
break
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Check for abort signal after each iteration
|
|
28
|
+
if (signal?.aborted) {
|
|
29
|
+
throw new AbortError()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/index.ts
ADDED
package/src/sleep.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// adopted from https://github.com/franciscop/use-async/blob/master/src/index.js
|
|
2
|
+
|
|
3
|
+
import { useEffect, useLayoutEffect } from 'react'
|
|
4
|
+
import { AbortError } from './errors'
|
|
5
|
+
|
|
6
|
+
const DEBUG_LEVEL = 0 // You can adjust this based on your needs
|
|
7
|
+
|
|
8
|
+
type Cleanup = () => void
|
|
9
|
+
|
|
10
|
+
type AsyncEffectCallback = (
|
|
11
|
+
signal: AbortSignal,
|
|
12
|
+
...deps: any[]
|
|
13
|
+
) => Promise<Cleanup | void> | void
|
|
14
|
+
|
|
15
|
+
export function useAsyncEffect(cb: AsyncEffectCallback, deps: any[] = []): void {
|
|
16
|
+
useAsyncEffectOfType(useEffect, cb, deps)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useAsyncLayoutEffect(cb: AsyncEffectCallback, deps: any[] = []): void {
|
|
20
|
+
useAsyncEffectOfType(useLayoutEffect, cb, deps)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function useAsyncEffectOfType(
|
|
24
|
+
type: Function,
|
|
25
|
+
cb: AsyncEffectCallback,
|
|
26
|
+
deps: any[] = []
|
|
27
|
+
): void {
|
|
28
|
+
type(() => {
|
|
29
|
+
const controller = new AbortController()
|
|
30
|
+
const signal = controller.signal
|
|
31
|
+
|
|
32
|
+
// wrap in try in case its not async (for simple use cases)
|
|
33
|
+
try {
|
|
34
|
+
const value = cb(signal, ...deps)
|
|
35
|
+
|
|
36
|
+
Promise.resolve(value)
|
|
37
|
+
.then(async (res) => {
|
|
38
|
+
if (res && typeof res === 'function') {
|
|
39
|
+
if (signal.aborted) return res()
|
|
40
|
+
signal.addEventListener('abort', res)
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
.catch(handleError)
|
|
44
|
+
} catch (error) {
|
|
45
|
+
handleError(error)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function handleError(error: any) {
|
|
49
|
+
if (error instanceof AbortError) {
|
|
50
|
+
if (DEBUG_LEVEL > 2) {
|
|
51
|
+
console.info(`🐛 useAsyncEffect aborted: ${error.message}`)
|
|
52
|
+
}
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// JS handles aborting a promise as an error. Thus, ignore them since they're a normal part
|
|
57
|
+
// of the expected async workflow
|
|
58
|
+
if (typeof error === 'object' && error.name === 'AbortError') {
|
|
59
|
+
return null
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Real errors, bubble it up since the CB is expected to handle the
|
|
63
|
+
// errors by itself, so this is like a "fatal error" that should've
|
|
64
|
+
// been handled by the devs
|
|
65
|
+
throw error
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return () => {
|
|
69
|
+
if (signal.aborted) return
|
|
70
|
+
controller.abort()
|
|
71
|
+
}
|
|
72
|
+
}, deps)
|
|
73
|
+
}
|