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

feat(mobx): add support for AbortSignal for reaction, autorun and sync when #3727

Merged
merged 7 commits into from
Jul 18, 2023

Conversation

rluvaton
Copy link
Contributor

@rluvaton rluvaton commented Jul 17, 2023

Code change checklist

  • Added/updated unit tests
  • Updated /docs. For new functionality, at least API.md should be updated
  • Verified that there is no significant performance drop (yarn mobx test:performance)
Performance output

Before:

❯ yarn mobx test:performance
yarn run v1.22.19
$ yarn workspace mobx test:performance
$ yarn perf proxy && yarn perf legacy
$ scripts/perf.sh proxy
TAP version 13
# proxy - one observes ten thousand that observe one
ok 1 should be strictly equal
ok 2 should be strictly equal
One observers many observes one - Started/Updated in 15/19 ms.
# proxy - five hundrend properties that observe their sibling
ok 3 should be strictly equal
ok 4 should be strictly equal
500 props observing sibling -  Started/Updated in 1/1 ms.
# proxy - late dependency change
ok 5 should be strictly equal
Late dependency change - Updated in 37ms.
# proxy - lots of unused computables
ok 6 should be strictly equal
ok 7 should be strictly equal
Unused computables -   Updated in 6 ms.
# proxy - many unreferenced observables
ok 8 should be strictly equal
Unused observables -  Updated in 7 ms.
# proxy - array reduce
ok 9 should be strictly equal
ok 10 should be strictly equal
ok 11 should be strictly equal
ok 12 should be strictly equal
Array reduce -  Started/Updated in 11/15 ms.
# proxy - array classic loop
ok 13 should be strictly equal
ok 14 should be strictly equal
ok 15 should be strictly equal
ok 16 should be strictly equal
ok 17 should be strictly equal
Array loop -  Started/Updated in 71/125 ms.
# proxy - order system observed
ok 18 should be strictly equal
ok 19 should be strictly equal
ok 20 should be strictly equal
Order system batched: false tracked: true  Started/Updated in 147/21 ms.
# proxy - order system batched observed
ok 21 should be strictly equal
ok 22 should be strictly equal
ok 23 should be strictly equal
Order system batched: true tracked: true  Started/Updated in 35/26 ms.
# proxy - order system lazy
ok 24 should be strictly equal
ok 25 should be strictly equal
ok 26 should be strictly equal
Order system batched: false tracked: false  Started/Updated in 43/14 ms.
# proxy - order system batched lazy
ok 27 should be strictly equal
ok 28 should be strictly equal
ok 29 should be strictly equal
Order system batched: true tracked: false  Started/Updated in 45/15 ms.
# proxy - create array

Create array -  Created in 48ms.
# proxy - create array (fast)

Create array (non-recursive)  Created in 20ms.
# proxy - observe and dispose
Observable with many observers  + dispose: 110ms
# proxy - sort
expensive sort: created 684
expensive sort: updated 4569
expensive sort: disposed 68
ok 30 should be strictly equal
native plain sort: updated 121
# proxy - computed temporary memoization
ok 31 should be strictly equal
computed memoization 3ms
# proxy - Map: initializing
Initilizing 100000 maps: 15 ms.
# proxy - Map: looking up properties
Looking up 100 map properties 1000 times: 5 ms.
# proxy - Map: setting and deleting properties
Setting and deleting 100 map properties 1000 times: 31 ms.
# (anonymous)


Completed performance suite in 6.594 sec.

1..31
# tests 31
# pass  31

# ok


real    0m6.774s
user    0m7.846s
sys     0m0.230s
$ scripts/perf.sh legacy
TAP version 13
# legacy - one observes ten thousand that observe one
ok 1 should be strictly equal
ok 2 should be strictly equal
One observers many observes one - Started/Updated in 15/15 ms.
# legacy - five hundrend properties that observe their sibling
ok 3 should be strictly equal
ok 4 should be strictly equal
500 props observing sibling -  Started/Updated in 0/1 ms.
# legacy - late dependency change
ok 5 should be strictly equal
Late dependency change - Updated in 36ms.
# legacy - lots of unused computables
ok 6 should be strictly equal
ok 7 should be strictly equal
Unused computables -   Updated in 6 ms.
# legacy - many unreferenced observables
ok 8 should be strictly equal
Unused observables -  Updated in 7 ms.
# legacy - array reduce
ok 9 should be strictly equal
ok 10 should be strictly equal
ok 11 should be strictly equal
ok 12 should be strictly equal
Array reduce -  Started/Updated in 12/15 ms.
# legacy - array classic loop
ok 13 should be strictly equal
ok 14 should be strictly equal
ok 15 should be strictly equal
ok 16 should be strictly equal
ok 17 should be strictly equal
Array loop -  Started/Updated in 71/124 ms.
# legacy - order system observed
ok 18 should be strictly equal
ok 19 should be strictly equal
ok 20 should be strictly equal
Order system batched: false tracked: true  Started/Updated in 148/21 ms.
# legacy - order system batched observed
ok 21 should be strictly equal
ok 22 should be strictly equal
ok 23 should be strictly equal
Order system batched: true tracked: true  Started/Updated in 35/26 ms.
# legacy - order system lazy
ok 24 should be strictly equal
ok 25 should be strictly equal
ok 26 should be strictly equal
Order system batched: false tracked: false  Started/Updated in 45/14 ms.
# legacy - order system batched lazy
ok 27 should be strictly equal
ok 28 should be strictly equal
ok 29 should be strictly equal
Order system batched: true tracked: false  Started/Updated in 46/15 ms.
# legacy - create array

Create array -  Created in 49ms.
# legacy - create array (fast)

Create array (non-recursive)  Created in 20ms.
# legacy - observe and dispose
Observable with many observers  + dispose: 112ms
# legacy - sort
expensive sort: created 693
expensive sort: updated 4804
expensive sort: disposed 67
ok 30 should be strictly equal
native plain sort: updated 147
# legacy - computed temporary memoization
ok 31 should be strictly equal
computed memoization 2ms
# legacy - Map: initializing
Initilizing 100000 maps: 15 ms.
# legacy - Map: looking up properties
Looking up 100 map properties 1000 times: 4 ms.
# legacy - Map: setting and deleting properties
Setting and deleting 100 map properties 1000 times: 28 ms.
# (anonymous)


Completed performance suite in 6.846 sec.

1..31
# tests 31
# pass  31

# ok


real    0m7.024s
user    0m8.059s
sys     0m0.231s
✨  Done in 15.01s.

After:

❯ yarn mobx test:performance
yarn run v1.22.19
$ yarn workspace mobx test:performance
$ yarn perf proxy && yarn perf legacy
$ scripts/perf.sh proxy
TAP version 13
# proxy - one observes ten thousand that observe one
ok 1 should be strictly equal
ok 2 should be strictly equal
One observers many observes one - Started/Updated in 15/16 ms.
# proxy - five hundrend properties that observe their sibling
ok 3 should be strictly equal
ok 4 should be strictly equal
500 props observing sibling -  Started/Updated in 1/0 ms.
# proxy - late dependency change
ok 5 should be strictly equal
Late dependency change - Updated in 38ms.
# proxy - lots of unused computables
ok 6 should be strictly equal
ok 7 should be strictly equal
Unused computables -   Updated in 6 ms.
# proxy - many unreferenced observables
ok 8 should be strictly equal
Unused observables -  Updated in 8 ms.
# proxy - array reduce
ok 9 should be strictly equal
ok 10 should be strictly equal
ok 11 should be strictly equal
ok 12 should be strictly equal
Array reduce -  Started/Updated in 12/14 ms.
# proxy - array classic loop
ok 13 should be strictly equal
ok 14 should be strictly equal
ok 15 should be strictly equal
ok 16 should be strictly equal
ok 17 should be strictly equal
Array loop -  Started/Updated in 71/126 ms.
# proxy - order system observed
ok 18 should be strictly equal
ok 19 should be strictly equal
ok 20 should be strictly equal
Order system batched: false tracked: true  Started/Updated in 147/23 ms.
# proxy - order system batched observed
ok 21 should be strictly equal
ok 22 should be strictly equal
ok 23 should be strictly equal
Order system batched: true tracked: true  Started/Updated in 34/25 ms.
# proxy - order system lazy
ok 24 should be strictly equal
ok 25 should be strictly equal
ok 26 should be strictly equal
Order system batched: false tracked: false  Started/Updated in 42/15 ms.
# proxy - order system batched lazy
ok 27 should be strictly equal
ok 28 should be strictly equal
ok 29 should be strictly equal
Order system batched: true tracked: false  Started/Updated in 45/15 ms.
# proxy - create array

Create array -  Created in 48ms.
# proxy - create array (fast)

Create array (non-recursive)  Created in 19ms.
# proxy - observe and dispose
Observable with many observers  + dispose: 113ms
# proxy - sort
expensive sort: created 683
expensive sort: updated 4582
expensive sort: disposed 68
ok 30 should be strictly equal
native plain sort: updated 120
# proxy - computed temporary memoization
ok 31 should be strictly equal
computed memoization 3ms
# proxy - Map: initializing
Initilizing 100000 maps: 15 ms.
# proxy - Map: looking up properties
Looking up 100 map properties 1000 times: 5 ms.
# proxy - Map: setting and deleting properties
Setting and deleting 100 map properties 1000 times: 30 ms.
# (anonymous)


Completed performance suite in 6.608 sec.

1..31
# tests 31
# pass  31

# ok


real    0m6.770s
user    0m7.779s
sys     0m0.275s
$ scripts/perf.sh legacy
TAP version 13
# legacy - one observes ten thousand that observe one
ok 1 should be strictly equal
ok 2 should be strictly equal
One observers many observes one - Started/Updated in 15/15 ms.
# legacy - five hundrend properties that observe their sibling
ok 3 should be strictly equal
ok 4 should be strictly equal
500 props observing sibling -  Started/Updated in 0/1 ms.
# legacy - late dependency change
ok 5 should be strictly equal
Late dependency change - Updated in 36ms.
# legacy - lots of unused computables
ok 6 should be strictly equal
ok 7 should be strictly equal
Unused computables -   Updated in 7 ms.
# legacy - many unreferenced observables
ok 8 should be strictly equal
Unused observables -  Updated in 7 ms.
# legacy - array reduce
ok 9 should be strictly equal
ok 10 should be strictly equal
ok 11 should be strictly equal
ok 12 should be strictly equal
Array reduce -  Started/Updated in 11/15 ms.
# legacy - array classic loop
ok 13 should be strictly equal
ok 14 should be strictly equal
ok 15 should be strictly equal
ok 16 should be strictly equal
ok 17 should be strictly equal
Array loop -  Started/Updated in 71/127 ms.
# legacy - order system observed
ok 18 should be strictly equal
ok 19 should be strictly equal
ok 20 should be strictly equal
Order system batched: false tracked: true  Started/Updated in 151/21 ms.
# legacy - order system batched observed
ok 21 should be strictly equal
ok 22 should be strictly equal
ok 23 should be strictly equal
Order system batched: true tracked: true  Started/Updated in 36/26 ms.
# legacy - order system lazy
ok 24 should be strictly equal
ok 25 should be strictly equal
ok 26 should be strictly equal
Order system batched: false tracked: false  Started/Updated in 43/14 ms.
# legacy - order system batched lazy
ok 27 should be strictly equal
ok 28 should be strictly equal
ok 29 should be strictly equal
Order system batched: true tracked: false  Started/Updated in 46/14 ms.
# legacy - create array

Create array -  Created in 50ms.
# legacy - create array (fast)

Create array (non-recursive)  Created in 20ms.
# legacy - observe and dispose
Observable with many observers  + dispose: 112ms
# legacy - sort
expensive sort: created 697
expensive sort: updated 4851
expensive sort: disposed 74
ok 30 should be strictly equal
native plain sort: updated 129
# legacy - computed temporary memoization
ok 31 should be strictly equal
computed memoization 2ms
# legacy - Map: initializing
Initilizing 100000 maps: 14 ms.
# legacy - Map: looking up properties
Looking up 100 map properties 1000 times: 4 ms.
# legacy - Map: setting and deleting properties
Setting and deleting 100 map properties 1000 times: 29 ms.
# (anonymous)


Completed performance suite in 6.887 sec.

1..31
# tests 31
# pass  31

# ok


real    0m7.059s
user    0m8.090s
sys     0m0.249s
✨  Done in 14.79s.

@changeset-bot
Copy link

changeset-bot bot commented Jul 17, 2023

🦋 Changeset detected

Latest commit: 43e0cfe

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
mobx Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rluvaton
Copy link
Contributor Author

I don't understand why all of a sudden the test failed when I added the changelog...

@urugator
Copy link
Collaborator

What's the use case?

@rluvaton
Copy link
Contributor Author

rluvaton commented Jul 18, 2023

cleaning up reaction when unmounting

In our app when we exit the page we want to abort all pending requests and clean the store, we abort all the requests using AbortSignal, and would like to pass the same signal to the reaction

current workaround:

clearAC.signal.addEventListener(
	'abort',
	reaction(
		() => something,
		myFn,
	),
	{
		once: true
	}
);

@urugator
Copy link
Collaborator

I see, thank you.

docs/reactions.md Outdated Show resolved Hide resolved
Comment on lines 369 to 371
An AbortSignal object instance
for `when` allows you to abort waiting for the reaction via an AbortController. This will also cause the returned promise to reject with an error "WHEN_ABORTED". This option is ignored when using an effect function, and only applies with the promised based version.
for `autorun` and `reaction` allow you to dispose the reaction via the AbortController.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace with

An AbortSignal object instance; can be used as an alternative method for disposal.<br>
`when`: This option is available only for the promise based version. When aborted, the promise rejects with the "WHEN_ABORTED" error.

Feel free to fix grammar or typos if necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When reading:

when: This option is available only

it seems like it's only for when

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean like the whole thing? Btw when delegates to autorun, can't we now support the non-promise based version as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, adding support

Copy link
Contributor Author

@rluvaton rluvaton Jul 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, the non-promised version won't throw an error as it won't get caught...

@rluvaton rluvaton changed the title feat(mobx): add support for AbortSignal for reaction and autorun feat(mobx): add support for AbortSignal for reaction, autorun and sync when Jul 18, 2023
docs/reactions.md Outdated Show resolved Hide resolved
@urugator
Copy link
Collaborator

Looks good, thank you!

@urugator urugator merged commit bebd5f0 into mobxjs:main Jul 18, 2023
1 check passed
@rluvaton rluvaton deleted the add-support-for-abort-signal branch July 18, 2023 18:25
@rluvaton
Copy link
Contributor Author

thank you!! hope to contribute soon!

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

Successfully merging this pull request may close these issues.

2 participants