-
Notifications
You must be signed in to change notification settings - Fork 26.6k
Several commits for resource() #59024
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
Conversation
0bfb183
to
8923549
Compare
request.set(undefined); | ||
expect(echoResource.status()).toBe(ResourceStatus.Idle); | ||
}); | ||
it('set() should abort a pending load', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mega-nit: new line to add spacing between tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unmergeable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Reviewed-for: public-api
Reviewed-for: fw-core
8923549
to
c9d2703
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reviewed-for: public-api
I really like the defaultValue on resource. Having not an Thanks for that! |
c9d2703
to
b4c6e01
Compare
b4c6e01
to
62bdd74
Compare
Originally the `T` in `Resource<T>` represented the resolved type of the resource, and `undefined` was explicitly added to this type in the `.value` signal. This turned out to be problematic, as it wasn't possible to write a type for a resource which didn't return `undefined` values. Such a type is useful for 2 reasons: 1. to support narrowing of the resource type when `Resource.hasValue()` returns `true`. 2. for resources which use a different value instead of `undefined` to represent not having a value (for example, array resources which want to use `[]` as their default). Instead, this commit changes `resource()` and `rxResource()` to return an explicit `ResourceRef<T|undefined>`, and removes the union with `undefined` from all types related to the resource's value. This way, it's trivially possible to write `Resource<T>` to represent resources where `.value` only returns `T`. `hasValue()` then actually works to perform narrowing, by narrowing the resource type to `Exclude<T, undefined>`.
When the reactive `request` of a resource() notifies, it transitions to the Loading state, fires the loader, and eventually transitions to Resolved. With the prior implementation, a change of the `request` will queue the effect, but the state remains unchanged until the effect actually runs. For a brief period, the resource is in a state where the request has changed, but the state has yet to update. This is problematic if we want to use resources in certain contexts where we care about the state of the resource in a synchronous way. For example, an async validator backed by a resource might be checked after an update: ``` value.set(123); if (validator.value()) { // value is still valid, even though the resource is dirty and will soon // flip to loading state (returning value(): undefined) while revalidating } ``` To address this timing concern, `linkedSignal()` is used within the `resource()` to synchronously transition the state in response to the request changing. This ensures any followup reads see a consistent view of the resource regardless of whether the effect has run. This also addresses a race condition where `.set()` behaves differently on a `resource()` depending on whether or not the effect has run.
62bdd74
to
f21a303
Compare
Caretaker: this PR is sensitive to backsliding. we need to patch cl/716243172 so far (and potentially more depending on presubmit failures). |
This PR was merged into the repository by commit 01fffdb. The changes were merged into the following branches: main, 19.1.x |
…gs (#59024) Originally the `T` in `Resource<T>` represented the resolved type of the resource, and `undefined` was explicitly added to this type in the `.value` signal. This turned out to be problematic, as it wasn't possible to write a type for a resource which didn't return `undefined` values. Such a type is useful for 2 reasons: 1. to support narrowing of the resource type when `Resource.hasValue()` returns `true`. 2. for resources which use a different value instead of `undefined` to represent not having a value (for example, array resources which want to use `[]` as their default). Instead, this commit changes `resource()` and `rxResource()` to return an explicit `ResourceRef<T|undefined>`, and removes the union with `undefined` from all types related to the resource's value. This way, it's trivially possible to write `Resource<T>` to represent resources where `.value` only returns `T`. `hasValue()` then actually works to perform narrowing, by narrowing the resource type to `Exclude<T, undefined>`. PR Close #59024
When the reactive `request` of a resource() notifies, it transitions to the Loading state, fires the loader, and eventually transitions to Resolved. With the prior implementation, a change of the `request` will queue the effect, but the state remains unchanged until the effect actually runs. For a brief period, the resource is in a state where the request has changed, but the state has yet to update. This is problematic if we want to use resources in certain contexts where we care about the state of the resource in a synchronous way. For example, an async validator backed by a resource might be checked after an update: ``` value.set(123); if (validator.value()) { // value is still valid, even though the resource is dirty and will soon // flip to loading state (returning value(): undefined) while revalidating } ``` To address this timing concern, `linkedSignal()` is used within the `resource()` to synchronously transition the state in response to the request changing. This ensures any followup reads see a consistent view of the resource regardless of whether the effect has run. This also addresses a race condition where `.set()` behaves differently on a `resource()` depending on whether or not the effect has run. PR Close #59024
When the reactive `request` of a resource() notifies, it transitions to the Loading state, fires the loader, and eventually transitions to Resolved. With the prior implementation, a change of the `request` will queue the effect, but the state remains unchanged until the effect actually runs. For a brief period, the resource is in a state where the request has changed, but the state has yet to update. This is problematic if we want to use resources in certain contexts where we care about the state of the resource in a synchronous way. For example, an async validator backed by a resource might be checked after an update: ``` value.set(123); if (validator.value()) { // value is still valid, even though the resource is dirty and will soon // flip to loading state (returning value(): undefined) while revalidating } ``` To address this timing concern, `linkedSignal()` is used within the `resource()` to synchronously transition the state in response to the request changing. This ensures any followup reads see a consistent view of the resource regardless of whether the effect has run. This also addresses a race condition where `.set()` behaves differently on a `resource()` depending on whether or not the effect has run. PR Close #59024
…gs (angular#59024) Originally the `T` in `Resource<T>` represented the resolved type of the resource, and `undefined` was explicitly added to this type in the `.value` signal. This turned out to be problematic, as it wasn't possible to write a type for a resource which didn't return `undefined` values. Such a type is useful for 2 reasons: 1. to support narrowing of the resource type when `Resource.hasValue()` returns `true`. 2. for resources which use a different value instead of `undefined` to represent not having a value (for example, array resources which want to use `[]` as their default). Instead, this commit changes `resource()` and `rxResource()` to return an explicit `ResourceRef<T|undefined>`, and removes the union with `undefined` from all types related to the resource's value. This way, it's trivially possible to write `Resource<T>` to represent resources where `.value` only returns `T`. `hasValue()` then actually works to perform narrowing, by narrowing the resource type to `Exclude<T, undefined>`. PR Close angular#59024
When the reactive `request` of a resource() notifies, it transitions to the Loading state, fires the loader, and eventually transitions to Resolved. With the prior implementation, a change of the `request` will queue the effect, but the state remains unchanged until the effect actually runs. For a brief period, the resource is in a state where the request has changed, but the state has yet to update. This is problematic if we want to use resources in certain contexts where we care about the state of the resource in a synchronous way. For example, an async validator backed by a resource might be checked after an update: ``` value.set(123); if (validator.value()) { // value is still valid, even though the resource is dirty and will soon // flip to loading state (returning value(): undefined) while revalidating } ``` To address this timing concern, `linkedSignal()` is used within the `resource()` to synchronously transition the state in response to the request changing. This ensures any followup reads see a consistent view of the resource regardless of whether the effect has run. This also addresses a race condition where `.set()` behaves differently on a `resource()` depending on whether or not the effect has run. PR Close angular#59024
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
No description provided.