Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Saborter Changelog

## v2.1.0 (March 18th, 2026)

### New Features

- Added break promises without signal [#56](https://github.com/TENSIILE/saborter/pull/56)

## v2.0.1 (March 1th, 2026)

### Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "saborter",
"version": "2.0.1",
"version": "2.1.0",
"description": "A simple and efficient library for canceling asynchronous requests using AbortController",
"main": "dist/index.cjs.js",
"module": "dist/index.es.js",
Expand Down
76 changes: 70 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ We constantly encounter situations where an incipient request needs to be cancel
| The signal will always be new. It's no coincidence that a previously disabled signal can appear from outside, which breaks all logic. | ✅ | ❌ |
| Built-in debounce functionality. | ✅ | ❌ |
| Availability of ponyfills in the set. | ✅ | ❌ |
| Interrupting promises. | ✅ | ❌ |

## 🚀 Quick Start

Expand Down Expand Up @@ -113,11 +114,12 @@ handleSearch('ab'); // The first request is canceled, a new one is started
handleSearch('abc'); // The second request is canceled, a new one is started
```

### 2. Automatic cancellation of requests
### 2. Automatic cancellation of requests by timer

The `Aborter` class makes it easy to cancel running requests after a period of time:

```javascript
// Create an Aborter instance
const aborter = new Aborter();

// Start a long-running request and cancel the request after 2 seconds
Expand All @@ -136,6 +138,7 @@ The `Aborter` class allows integration with the debounce utility:
```javascript
import { debounce } from 'saborter/lib';

// Create an Aborter instance
const aborter = new Aborter();

// The request will be delayed for 2 seconds and then executed.
Expand All @@ -146,11 +149,35 @@ const results = aborter.try(
);
```

### 4. Multiple request aborts through a single `ReusableAborter` instance
### 4. Interrupting promises without a signal

If you want to cancel a task with a promise:

```javascript
import { Aborter } from 'saborter';

// Create an Aborter instance
const aborter = new Aborter();

// Create a helper function for delay
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

// The callback function can be restarted each time (by calling .try() again), which will interrupt the previous call and start it again.
// Or the `.abort()` method can be used to abort the callback function entirely.
const results = aborter.try(
async () => {
await delay(2000);
return Promise.resolve({ done: true });
}
);
```

### 5. Multiple request aborts through a single `ReusableAborter` instance

The `ReusableAborter` class allows you to easily cancel requests an unlimited number of times while preserving all listeners:

```javascript
// Create an ReusableAborter instance
const reusableAborter = new ReusableAborter();

// Adding a subscription to an interrupt event
Expand All @@ -159,15 +186,14 @@ reusableAborter.addEventListener('abort', (e) => console.log('aborted', e));
// Start a long-running request and cancel the request after 2 seconds
const fetchPosts = async () => {
const response = await fetch('/api/posts', { signal: reusableAborter.signal });

return await response.json();
};

reusableAborter.abort(); // call of the listener -> console.log('aborted', e)
reusableAborter.abort(); // listener recall -> console.log('aborted', e)
```

### 5. Working with Multiple Requests
### 6. Working with Multiple Requests

You can create separate instances for different groups of requests:

Expand Down Expand Up @@ -301,6 +327,8 @@ const result = await aborter.try(async (signal) => {
});
```

**Automatic response unpacking:**

You can either write `.json()` or not write it from the `fetch` function. You can immediately return the `fetch` result.

> [!NOTE]
Expand All @@ -315,11 +343,11 @@ const users = await aborter.try<User[]>((signal) => {
> [!WARNING]
> You cannot override typing via a generic if the callback already has a specific return type.

```javascript
```typescript
const users = await aborter.try<User[]>(async (signal) => {
const response = await fetch('/api/users', { signal });
// There will be a typing error!
return await response.json() as { data: User[] }
return (await response.json()) as { data: User[] };
});
```

Expand All @@ -338,6 +366,42 @@ const response = await aborter.try(
const data = await response.json();
```

**Calling a method without a signal:**

The `.try()` method can be called without removing the `signal` from the callback argument if you don't need it.
For example, if there's a promise you want to break, you can call it inside the callback.

```typescript
const results = aborter.try(async () => {
await delay(2000);
return Promise.resolve({ done: true });
});
```

It is also possible to abort requests (the same `fetch()`, for example) without transmitting a `signal`, but this is highly discouraged.
However, if it is not possible to transmit a `signal`, the aborter will abort its promise.

```typescript
// We create a wrapper around the request without being able to pass the signal
const requestPosts = async () => {
const response = await fetch('/api/posts');
return response.json();
};

try {
// We launch an HTTP request, after 1.5 seconds it will automatically terminate
const posts = await aborter.try(requestPosts, { timeout: 1500 });
setPosts(posts);
} catch (error) {
if (error instanceof AbortError) {
// We get an interrupt error and the setPosts setter won't be called
}
}
```

> [!NOTE]
> In this case, the wait for the request to be executed will be interrupted, but the request itself will still be executed.

**Examples using automatic cancellation after a time:**

```javascript
Expand Down
Binary file added unreleased-packages/saborter-2.1.0.tgz
Binary file not shown.
Loading