Skip to content

Commit

Permalink
Merge pull request #940 from thefrontside/with-resolvers-docs
Browse files Browse the repository at this point in the history
📄 Documentation  for `withResolvers()`
  • Loading branch information
cowboyd authored Dec 20, 2024
2 parents c286423 + 2d315e4 commit b9e4eff
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 9 deletions.
36 changes: 36 additions & 0 deletions lib/with-resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,48 @@ import { Err, Ok, Result } from "./result.ts";
import { action } from "./action.ts";
import type { Operation } from "./types.ts";

/**
* The return type of {@link withResolvers}. It contains an operation bundled with
* synchronous functions that determine its outcome.
*/
export interface WithResolvers<T> {
/*
* An {@link Operation} that will either produce a value or raise an
* exception when either `resolve` or `reject` is called. No matter
* how many times this operation is yielded to, it will always
* produce the same effect.
*/
operation: Operation<T>;

/**
* Cause {@link operation} to produce `value`. If either `resolve`
* or`reject` has been called before, this will have no effect.
*
* @param value - the value to produce
*/
resolve(value: T): void;

/**
* Cause {@link operation} to raise `Error`. Any calling operation
* waiting on `operation` will. Yielding to `operation` subsequently
* will also raise the same error. * If either `resolve` or`reject`
* has been called before, this will have no effect.
*
* @param error - the error to raise
*/
reject(error: Error): void;
}

/**
* Create an {link @Operation} and two functions to resolve or reject
* it, corresponding to the two parameters passed to the executor of
* the {@link action} constructor. This is the Effection equivalent of
* [Promise.withResolvers()]{@link
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers}
*
* @returns an operation and its resolvers.
*/

export function withResolvers<T>(description?: string): WithResolvers<T> {
let continuations = new Set<(result: Result<T>) => void>();
let result: Result<T> | undefined = undefined;
Expand Down
52 changes: 43 additions & 9 deletions www/docs/async-rosetta-stone.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ know how to do it in Effection.
The congruence between vanilla JavaScript constructs and their Effection
counterparts is reflected in the “Async Rosetta Stone.”

| Async/Await | Effection |
| ---------------- | ----------------- |
| `await` | `yield*` |
| `async function` | `function*` |
| `Promise` | `Operation` |
| `new Promise()` | `action()` |
| `for await` | `for yield* each` |
| `AsyncIterable` | `Stream` |
| `AsyncIterator` | `Subscription` |
| Async/Await | Effection |
| --------------------------| ----------------- |
| `await` | `yield*` |
| `async function` | `function*` |
| `Promise` | `Operation` |
| `new Promise()` | `action()` |
| `Promise.withResolvers()` | `withResolvers()` |
| `for await` | `for yield* each` |
| `AsyncIterable` | `Stream` |
| `AsyncIterator` | `Subscription` |

## `await` \<=> `yield*`

Expand Down Expand Up @@ -154,6 +155,39 @@ A key difference is that the promise body will be executing immediately, but the
action body is only executed when the action is evaluated. Also, it is executed
anew every time the action is evaluated.

## `Promise.withResolvers()` \<=> `withResolvers()`

Both `Promise` and `Operation` can be constructed ahead of time without needing to begin the process that will resolve it. To do this with
a `Promise`, use the `Promise.withResolvers()` function:

```ts
async function main() {
let { promise, resolve } = Promise.withResolvers();

setTimeout(resolve, 1000);

await promise;

console.log("done!")
}
```

In effection:

```ts
import { withResolvers } from "effection";

function* main() {
let { operation, resolve } = withResolvers();

setTimeout(resolve, 1000);

yield* operation;

console.log("done!");
};
```

## `for await` \<=> `for yield* each`

Loop over an AsyncIterable with `for await`:
Expand Down

0 comments on commit b9e4eff

Please sign in to comment.