-
Notifications
You must be signed in to change notification settings - Fork 54
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
Feedback and Concerns on the Proposal Signals #105
Comments
Thanks for raising this @SukkaW. I'll try to address each point from my own perspective. Other individuals may have additional thoughts. Regarding TC39 as the vehicle for standardization. We don't have to do this through TC39. We started there because we heard non-Web use cases during our interviews, and because various members had strong prior experience with the TC39 process. That said, the largest set of use cases are UI related. If TC39 turns out to not be the right path, we can certainly shift to a different standards body. Regarding Proxy. The Proxy, in itself, doesn't provide the infrastructure for interoperable signals. Signals have a very specific acyclic graph data structure and a "push then pull" algorithm. With proxies alone, the goals of this proposal cannot be achieved, and certainly not in an interoperable way. Signals is great paired with proxies, where a signal can be the underlying storage mechanism for a Proxy-based state store. Regarding |
Thank you for your reply and for addressing the points I raised!
The main argument here is that if it's already possible to implement the functionalities and the behaviors of This is similar to why the low-level data structures like Linked List and the Queue are not included in the ECMA-262 spec and W3C/WHATWG standards. They are useful, but JavaScript has already provided low-level building blocks that developers can use to create such libraries. The runtime will eventually optimize the execution if the approach and the code path become popular. |
IMHO, what JavaScript really requires is a low-level building block designed for incremental computation. And I understand it is the key element that What JavaScript doesn't need is a specific set of APIs only for building application responds to user interactions. |
My thoughts: The successful lesson is Promise, which was standardized in tc39 and used when the async function was proposed. A lesson learned from the failure is AbortSignal, which is standardized on the Web but has extensive needs in the entire ecosystem. This leads to the need for cross-environment coordination like WinterCG to solve the problem of cross-ecological consistency, but this actually shows that it should be implemented in tc39 Standardization (note that fetch is different because fetch involves IO, but AbortSignal does not). I'm not sure signal has widespread use outside of rendering, so I'm not sure it should be in tc39. |
I agree that Promise is a success and AbortSignal is not, and the venue is largely why that’s the case. Rendering is very much also a server-side concern, so i’m much more optimistic that signals belongs in TC39. |
As I have already pointed out initially, the
The most common usage of those short-lived and non-persistent states are implementing user interactions, and that's it. As for the server-side javascript and the rendering, here I quote from my initial feedback:
We are not making persistent state (E.g. on-disk databases like MySQL, SQLite, PostgreSQL) reactive, right? |
SSR is pretty active in today's Web (nextjs etc) but let's say, should it also exist in the XS engine? Will you use it in general computation? (It's a maybe for me because I can see the benefit of incremental computing). |
JavaScript does need a low-level building block for implementing incremental computation (as I have already mentioned in #105 (comment)), but it doesn't necessarily be a The |
It's equally common in a webserver to respond to requests - they're often stateless, modulo a database, across requests, but quite stateful during the many distinct and separately located parts of a given request/response.
|
Indeed, The same principle applies to Computed. What JavaScript needs is a low-level building block for implementing Incremental Computation (upon which |
Most non-rendering JS APIs I've worked on have almost immediately hit the desire for signals, primarily from the perspective of memo. Same for build tooling. Plenty of ways to construct a good memo function obviously, but none quite as robust as you get with signals. |
If you are talking about something like this: // A magic function `lazy()`.
// a() function will only execute when it is being referenced,
// and it will only execute once
const a = lazy(() => { /* something */ });
if (/* condition a */) {
/* ... */ = a();
} else if (/* condition b */) {
// no a();
} else {
/* ... */ = a();
}
if (/* condition c */) {
/* ... */ = a() + 1;
}
// a() will never evaluate if only condition b is truthy
// a() will only evaluate once even if both condition a and c is truthy Then what you need is the incremental computation, not the derived state. |
I feel truly mitigated: signals are amazing, and (in my opinion), the best solution (so far) for web applications. Giving them the opportunity to exist as a native API is great for developers and performances. However, I clearly see some limits:
Finally, if it's part of the tc39 instead of w3c, we may thing about more "integrated" signals (and let the engine do the magic): signal a = 5; // equivalent of let a = 5
signal b = computed {
return a + 2;
}
const unwatch = watch {
console.log(b);
} TC39 opens the gate to new language possibilities and integrations, where the w3c is better suitable for to API. In my opinion, I suggest, it may be worth waiting 1-2 years for a real stabilisation and wide adoption (thus exposing limits, and introducing improvements), before jumping immediately into something still in early stages. |
@SukkaW Would you prefer to break this proposal into:
I think that would be a logical split. Two proposals entails more work for the authors, but it would greatly simplify the TC39 proposal, possibly increasing the chances of approval and inclusion in the standard. The I'm excited about this proposal, and I hope it lands somehow. State management is such a critical part of a language. This reactive approach has emerged over time as the preferred way to manage state in interactive JS applications, so I think it makes sense to standardize and provide a common ground for interoperability. |
That would be awesome! Also, some other thoughts: The incremental computation must be a language feature, not a built-in class. Because class introduces js object, js object introduces memory and GC pressure, memory and GC pressure introduces performance overhead, tick-tack-toe. |
I think engines can optimize away what appears to be an object in this case. They're not bound to represent it as an object in memory, as long as it functions according to spec. So performance shouldn't be an issue, at least in the popular, highly optimized engines. It's not the syntax, but the semantics of the proposal, how the graph is to be implemented, that will affect performance. Classes do have some benefits.
While special syntax would be nice, I just want this proposal to get accepted :) |
Responding from a library author perspective:
Polyfills are not a happy fallback here - think of And that ignores the fact that both Redux and Apollo Client are even used in normal backend code - completely outside of React applications. Also, going the route of "have the ecosystem establish a library for it instead of including it in the platform" is probably not a good idea - because it might not happen, and in the end you'll ship multiple different implementations to your users. Example case: If you use Apollo Client in Angular nowadays, you will ship Zen-Observable (because Apollo Client) and RxJs (because of Angular) to your users. => I'm very much in favor of this going through TC39. |
I also want to add that environments like Node.js shouldn't be seen as a synonym for CRUD servers. @phryneas has already mentioned frontend tooling. But there are even more fields like more action/task heavy servers, AI, IoT, hardware development, CLI tools, etc. which would not be implemented in a browser. Take this as an example: const counter = new Signal.State(0)
hardwareButton.addEventListener('push', () => {
counter.set(counter.get() + 1)
})
effect(() => {
printOn7SegmentDisplay(counter.get())
}) This could be the code for some click counter. The structure for applications like this is very close to what a browser application would look like. Just replace html buttons with hardware buttons and print the result to some special screen instead of the DOM. I also want to mention that I'm very happy to see this being worked on. My main use case might be browser centric as well but I'm playing around with how I could develop a web application with as few libraries as possible. And I figured out one of the biggest pain points is indeed state management. I've even started working on a library to tackle this problem and the result looks extremely similar to this proposal. If this proposal could be made more simple like some mentioned I'd be all here for it though. |
I am writing to express some concerns regarding the proposal to incorporate signals and reactive programming into the ECMAScript spec.
While I appreciate the potential benefits of signals for managing short-lived and non-persistent states within a JavaScript application—especially in the context of developing web applications and desktop/mobile applications (where the user interactions matter), I believe it's also important to consider the implications for server-side JavaScript. Server-side applications are often either stateless or persist states in an on-disk database rather than in memory. As such, the introduction of a
Signal
directly into the JavaScript language may not be beneficial in these contexts. Instead, it might be more appropriate to consider a runtime-specific implementation, such as a Web API. This approach would allow developers to adopt signals where they make sense, without imposing additional complexity on the language itself.Moreover, I would like to draw attention to the existing
Proxy
object in JavaScript, which already provides a low-level language agnostics for library authors to implement similar functionality. See also #101.Lastly, I would like to point out the similarities between the proposed
Signal
API and the deprecatedObject.observe
proposal. The latter also aimed to track object mutations and provide responsive callbacks, but it was ultimately withdrawn. I worry that the new signal proposal might essentially be a reiteration ofObject.observe
, and it could face similar challenges and criticisms.I believe it's crucial to thoroughly consider these points to ensure the continued robustness and versatility of JavaScript. I look forward to engaging in further discussions about this proposal and contributing to the evolution of the language.
Thank you for your time and consideration!
The text was updated successfully, but these errors were encountered: