Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(async): complete documentation #3887

Merged
merged 5 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
12 changes: 6 additions & 6 deletions async/abortable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// This module is browser compatible.

/**
* Make Promise abortable with the given signal.
* Make {@linkcode Promise} abortable with the given signal.
*
* @example
* ```typescript
* ```ts
* import { abortable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
* import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
*
Expand All @@ -19,10 +19,10 @@
*/
export function abortable<T>(p: Promise<T>, signal: AbortSignal): Promise<T>;
/**
* Make AsyncIterable abortable with the given signal.
* Make {@linkcode AsyncIterable} abortable with the given signal.
*
* @example
* ```typescript
* ```ts
* import { abortable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
* import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
*
Expand Down Expand Up @@ -61,7 +61,7 @@ export function abortable<T>(
* Make Promise abortable with the given signal.
*
* @example
* ```typescript
* ```ts
* import { abortablePromise } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
*
* const request = fetch("https://example.com");
Expand Down Expand Up @@ -97,7 +97,7 @@ export function abortablePromise<T>(
* Make AsyncIterable abortable with the given signal.
*
* @example
* ```typescript
* ```ts
* import { abortableAsyncIterable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
* import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
*
Expand Down
20 changes: 17 additions & 3 deletions async/deadline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,39 @@

import { delay } from "./delay.ts";

/** Options for {@linkcode Deadline}. */
export interface DeadlineOptions {
/** Signal used to abort the deadline. */
signal?: AbortSignal;
}

/** Error thrown when {@linkcode Deadline} times out. */
export class DeadlineError extends Error {
/**
* Constructs a new {@linkcode DeadlineError} instance.
*
* @example
* ```
* import { DeadlineError } from "https://deno.land/std@$STD_VERSION/async/deadline.ts";
*
* throw new DeadlineError();
* ```
*/
constructor() {
super("Deadline");
this.name = this.constructor.name;
}
}

/**
* Create a promise which will be rejected with {@linkcode DeadlineError} when a given delay is exceeded.
* Create a promise which will be rejected with {@linkcode DeadlineError} when
* a given delay is exceeded.
*
* NOTE: Prefer to use `AbortSignal.timeout` instead for the APIs accept `AbortSignal`.
* Note: Prefer to use {@linkcode AbortSignal.timeout} instead for the APIs
* that accept {@linkcode AbortSignal}.
*
* @example
* ```typescript
* ```ts
* import { deadline } from "https://deno.land/std@$STD_VERSION/async/deadline.ts";
* import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
*
Expand Down
8 changes: 4 additions & 4 deletions async/delay.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.

/** Options for {@linkcode delay}. */
export interface DelayOptions {
/** Signal used to abort the delay. */
signal?: AbortSignal;
Expand All @@ -12,11 +13,10 @@ export interface DelayOptions {
}

/**
* Resolve a Promise after a given amount of milliseconds.
* Resolve a {@linkcode Promise} after a given amount of milliseconds.
*
* @example
*
* ```typescript
* ```ts
* import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
*
* // ...
Expand All @@ -28,7 +28,7 @@ export interface DelayOptions {
* To allow the process to continue to run as long as the timer exists. Requires
* `--unstable` flag.
*
* ```typescript
* ```ts
* import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
*
* // ...
Expand Down
13 changes: 8 additions & 5 deletions async/mux_async_iterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ interface TaggedYieldedValue<T> {
}

/**
* The MuxAsyncIterator class multiplexes multiple async iterators into a single
* stream. It currently makes an assumption that the final result (the value
* returned and not yielded from the iterator) does not matter; if there is any
* result, it is discarded.
* Multiplexes multiple async iterators into a single stream. It currently
* makes an assumption that the final result (the value returned and not
* yielded from the iterator) does not matter; if there is any result, it is
* discarded.
*
* @example
* ```typescript
* ```ts
* import { MuxAsyncIterator } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
*
* async function* gen123(): AsyncIterableIterator<number> {
Expand Down Expand Up @@ -44,6 +44,7 @@ export class MuxAsyncIterator<T> implements AsyncIterable<T> {
#throws: any[] = [];
#signal = Promise.withResolvers<void>();

/** Add an async iterable to the stream */
iuioiua marked this conversation as resolved.
Show resolved Hide resolved
add(iterable: AsyncIterable<T>) {
++this.#iteratorCount;
this.#callIteratorNext(iterable[Symbol.asyncIterator]());
Expand All @@ -65,6 +66,7 @@ export class MuxAsyncIterator<T> implements AsyncIterable<T> {
this.#signal.resolve();
}

/** Returns an async iterator of the stream */
iuioiua marked this conversation as resolved.
Show resolved Hide resolved
async *iterate(): AsyncIterableIterator<T> {
while (this.#iteratorCount > 0) {
// Sleep until any of the wrapped iterators yields.
Expand All @@ -89,6 +91,7 @@ export class MuxAsyncIterator<T> implements AsyncIterable<T> {
}
}

/** Implements an async iterator for the stream */
iuioiua marked this conversation as resolved.
Show resolved Hide resolved
[Symbol.asyncIterator](): AsyncIterator<T> {
return this.iterate();
}
Expand Down
3 changes: 2 additions & 1 deletion async/pool.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.

/** Error message emitted from the thrown error while mapping. */
export const ERROR_WHILE_MAPPING_MESSAGE = "Threw while mapping.";

/**
Expand All @@ -14,7 +15,7 @@ export const ERROR_WHILE_MAPPING_MESSAGE = "Threw while mapping.";
* thrown by the iterator in an `AggregateError`.
*
* @example
* ```typescript
* ```ts
* import { pooledMap } from "https://deno.land/std@$STD_VERSION/async/pool.ts";
*
* const results = pooledMap(
Expand Down
65 changes: 51 additions & 14 deletions async/retry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,57 @@
import { assert } from "../assert/assert.ts";
import { _exponentialBackoffWithJitter } from "./_util.ts";

/**
* Error thrown in {@linkcode retry} once the maximum number of failed attempts
* has been reached.
*/
export class RetryError extends Error {
/**
* Constructs a new {@linkcode RetryError} instance.
*
* @example
* ```
* ```
iuioiua marked this conversation as resolved.
Show resolved Hide resolved
*/
constructor(cause: unknown, attempts: number) {
super(`Retrying exceeded the maxAttempts (${attempts}).`);
this.name = "RetryError";
this.cause = cause;
}
}

/** Options for {@linkcode retry}. */
export interface RetryOptions {
/** How much to backoff after each retry. This is `2` by default. */
/**
* How much to backoff after each retry.
*
* @default {2}
*/
multiplier?: number;
/** The maximum milliseconds between attempts. This is `60000` by default. */
/**
* The maximum milliseconds between attempts.
*
* @default {60000}
*/
maxTimeout?: number;
/** The maximum amount of attempts until failure. This is `5` by default. */
/**
* The maximum amount of attempts until failure.
*
* @default {5}
*/
maxAttempts?: number;
/** The initial and minimum amount of milliseconds between attempts. This is `1000` by default. */
/**
* The initial and minimum amount of milliseconds between attempts.
*
* @default {1000}
*/
minTimeout?: number;
/** Amount of jitter to introduce to the time between attempts. This is `1` for full jitter by default. */
/**
* Amount of jitter to introduce to the time between attempts. This is `1`
* for full jitter by default.
*
* @default {1}
*/
jitter?: number;
}

Expand All @@ -35,19 +68,23 @@ const defaultRetryOptions: Required<RetryOptions> = {

/**
* Calls the given (possibly asynchronous) function up to `maxAttempts` times.
* Retries as long as the given function throws.
* If the attempts are exhausted, throws an `RetryError` with `cause` set to the inner exception.
* Retries as long as the given function throws. If the attempts are exhausted,
* throws a {@linkcode RetryError} with `cause` set to the inner exception.
*
* The backoff is calculated by multiplying `minTimeout` with `multiplier` to the power of the current attempt counter (starting at 0 up to `maxAttempts - 1`). It is capped at `maxTimeout` however.
* How long the actual delay is, depends on `jitter`.
* The backoff is calculated by multiplying `minTimeout` with `multiplier` to
* the power of the current attempt counter (starting at 0 up to `maxAttempts
* - 1`). It is capped at `maxTimeout` however. How long the actual delay is,
* depends on `jitter`.
*
* When `jitter` is the default value of `1`, waits between two attempts for a randomized amount between 0 and the backoff time.
* With the default options the maximal delay will be `15s = 1s + 2s + 4s + 8s`. If all five attempts are exhausted the mean delay will be `9.5s = ½(4s + 15s)`.
* When `jitter` is the default value of `1`, waits between two attempts for a
* randomized amount between 0 and the backoff time. With the default options
* the maximal delay will be `15s = 1s + 2s + 4s + 8s`. If all five attempts
* are exhausted the mean delay will be `9.5s = ½(4s + 15s)`.
*
* When `jitter` is `0`, waits the full backoff time.
*
* @example
* ```typescript
* ```ts
* import { retry } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
* const req = async () => {
* // some function that throws sometimes
Expand All @@ -64,7 +101,7 @@ const defaultRetryOptions: Required<RetryOptions> = {
* ```
*
* @example
* ```typescript
* ```ts
* import { retry } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
* const req = async () => {
* // some function that throws sometimes
Expand All @@ -83,7 +120,7 @@ const defaultRetryOptions: Required<RetryOptions> = {
export async function retry<T>(
fn: (() => Promise<T>) | (() => T),
opts?: RetryOptions,
) {
): Promise<T> {
const options: Required<RetryOptions> = {
...defaultRetryOptions,
...opts,
Expand Down
17 changes: 9 additions & 8 deletions async/tee.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.

// Utility for representing n-tuple
type Tuple<T, N extends number> = N extends N
/** Utility for representing n-tuple. Used in {@linkcode tee}. */
export type Tuple<T, N extends number> = N extends N
? number extends N ? T[] : TupleOf<T, N, []>
: never;
type TupleOf<T, N extends number, R extends unknown[]> = R["length"] extends N
? R
: TupleOf<T, N, [T, ...R]>;

/** Utility for representing n-tuple of. Used in {@linkcode Tuple}. */
export type TupleOf<T, N extends number, R extends unknown[]> =
R["length"] extends N ? R
: TupleOf<T, N, [T, ...R]>;

interface QueueNode<T> {
value: T;
Expand Down Expand Up @@ -47,7 +49,7 @@ class Queue<T> {
}

/**
* Branches the given async iterable into the n branches.
* Branches the given async iterable into the `n` branches.
*
* @example
* ```ts
Expand Down Expand Up @@ -90,11 +92,10 @@ export function tee<T, N extends number = 2>(
}
}

const branches = Array.from({ length: n }).map(
return Array.from({ length: n }).map(
() => generator(),
) as Tuple<
AsyncIterable<T>,
N
>;
return branches;
}