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

RFC: async in signals #291

Closed
JoviDeCroock opened this issue Jan 5, 2023 · 1 comment
Closed

RFC: async in signals #291

JoviDeCroock opened this issue Jan 5, 2023 · 1 comment

Comments

@JoviDeCroock
Copy link
Member

JoviDeCroock commented Jan 5, 2023

When using the core signals library we are enabled to perform actions like

let isLoading = signal(true);
// Hypothetical deep-signal to react to objects
let result = deepSignal(undefined)

fetch(x).then(...)

however this is a lot of boilerplate code for something that could probably be both optimized and made ergonomic from our package standpoint. The issue here arises when we want to implement this flow in the core Preact library, we would have to resort to hooks/... so we're able to implement a similar flow.

Personally I have been a fan of the createResource API in Solid. Going from this thinking I would suggest us following a similar routes as the resource way of thinking, in practice this could look something like

const { isLoading, error, result } = createResource(asyncOperation);

This however leads me to a few thinking points as we have the open questions around whether or not we leverage Suspense as a loading mechanism and how do we make this work on the server? Currently we have preact-ssr-prepass that catches an async load entry and resolves as needed, this would not work if we don't op for the Suspense approach.

If we're opting out of Suspense we would probably need to make ourselves aware of loads when we are in a Node Environment so they can be awaited before rendering to a string (most likely would also need a way to be collected so it can be rehydrated if needed).

One last need here would be a reliable way to diff POJO signals as most results from async operations would lead to an object-like result.

This might be a stretch to support in Signals but as it currently stands I feel like there is no way outside of using hooks to reliably execute async operations.

@eddyw
Copy link
Contributor

eddyw commented Mar 21, 2023

What about something like this?

const signal = asyncSignal(defaultValue); // signal.status = "RESOLVED"
const signal = asyncSignal(Error(""));    // signal.status = "REJECTED"
const signal = asyncSignal();             // signal.status = "PENDING"

await fetch(foo)
  .then(signal.then)
  .catch(signal.catch)
  
signal.status; // RESOLVED | REJECTED | PENDING
signal.value;  // null | T
signal.error;  // null | Error

// Programmatically change values:
signal.value = "foo"; // signal.status => "RESOLVED"
signal.error = "";    // signal.status => "REJECTED"

Then it's easier to create other abstractions on top of this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants