skt-t1-byungi / aico

🦄 abort in coroutines

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

A.I.C.O 🦄

Abort In COroutines (promise)

npm npm

Inspired by Redux-Saga's Task cancellation, aico is designed to make promise cancellation simpler and more efficient. With a minimalist API, it integrates seamlessly with AbortController and TypeScript.

aico

(Title inspired by the Netflix series A.I.C.O on Netflix))

Example

import { aico } from 'aico'

const promise = aico(function* (signal) {
    try {
        yield fetch('/delay/100', { signal }) // <= This api takes 100ms.
        console.log('1. This is printed.')

        yield fetch('/delay/100', { signal }) // <= This api takes 100ms.
        console.log('2. This is not printed.')
    } finally {
        if (signal.aborted) {
            console.log('3. aborted!')
        }
    }
})

promise.catch(err => {
    console.log(`4. message: ${err.name}`)
    console.log(`5. isAborted: ${err.isAborted}`)
})

setTimeout(() => {
    promise.abort() // <= After 150ms
}, 150)
> output
1. This is printed.
3. aborted!
4. message: AbortError
5. isAborted: true

Install

npm install aico

API

new AbortInCoroutines(generator, options?)

Creates an abortable promise. Within the generator function, the yield statement behaves like await in an async function.

import { AbortInCoroutines } from 'aico'

const promise = new AbortInCoroutines(function* (signal) {
    const result = yield Promise.resolve('hello')
    return result
})

signal parameter is AbortSignal that can cancel DOM requests such as fetch.

const promise = new AbortInCoroutines(function* (signal) {
    const response = yield fetch('/api/request', { signal })
    // ...
})

promise.abort() // <= Abort `/api/request` request.

signal has an aborted property that indicates whether the promise was aborted or not.

const promise = new AbortInCoroutines(function* (signal) {
    try {
        /* ... */
    } finally {
        if (signal.aborted) {
            console.log('aborted!')
        }
    }
})

promise.abort() // => "aborted!"

If the yielded promise was created with AbortInCoroutines, the cancellation is propagated.

const subTask = () =>
    new AbortInCoroutines(function* (signal) {
        try {
            /* ... */
        } finally {
            if (signal.aborted) {
                console.log('subTask is aborted!')
            }
        }
    })

const promise = new AbortInCoroutines(function* () {
    yield subTask()
})

promise.abort() // => "subTask is aborted!"

options

signal

Allows for aborting the promise using an external AbortController signal.

const controller = new AbortController()

const promise = new AbortInCoroutines(
    function* (signal) {
        /* ... */
    },
    {
        signal: controller.signal,
    },
)

controller.abort()
unhandledRejection

If set to true, an unhandledRejection occurs. Default is false.

new AbortInCoroutines(
    function* () {
        /* ... */
    },
    {
        unhandledRejection: true,
    },
).abort()

promise.isAborted

Checks if the promise has been aborted.

console.log(promise.isAborted) // => false

promise.abort()

console.log(promise.isAborted) // => true

promise.abort()

Abort the promise manually.

aico(generator, options?)

A shorthand function as an alternative to new AbortInCoroutines().

import { aico } from 'aico'

const promise = aico(function* (signal) {
    /* ... */
})

Combinators

all(values)

An abortable version of Promise.all(). If one promise rejects, all other promises are automatically aborted.

race(values)

An abortable version of Promise.race(). If one promise rejects, all other promises are automatically aborted.

any(values)

An abortable version of Promise.any().

allSettled(values)

An abortable version of Promise.allSettled().

cast(promise)

When working with TypeScript, you may find type inference challenging for yielded promises.

import { aico, cast } from 'aico'

const promise = aico(function* () {
    const data = (yield fetchData()) as { value: string }

    // or
    const data = (yield fetchData()) as Awaited<ReturnType<typeof fetchData>>
})

Use cast for better type inference.

import { aico, cast } from 'aico'

const promise = aico(function* () {
    const data = yield* cast(fetchData())
})

License

MIT © skt-t1-byungi

About

🦄 abort in coroutines

License:MIT License


Languages

Language:TypeScript 100.0%