Skip to content

Add observables#260

Open
rflamand wants to merge 1 commit into
ImagingDataCommons:masterfrom
rflamand:feature/raffla/add_observable
Open

Add observables#260
rflamand wants to merge 1 commit into
ImagingDataCommons:masterfrom
rflamand:feature/raffla/add_observable

Conversation

@rflamand

@rflamand rflamand commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR introduces a new Observable class to the codebase, providing a self-contained, DOM-independent reactive value store. The Observable pattern enables efficient reactive programming within the application.
It's implemented as part of #239 , however, it should be usable by other components in the module.
The object is not used yet in this PR.
A follow up PR will use it (as explained in #239) to ensure that the color space gamut is dynamically updated.

Changes

Added: observable.js - A new Observable class that:

  • Holds a single value of any type
  • Notifies subscribers asynchronously (via microtask) when values change
  • Provides getValue(), setValue(), subscribe(), unsubscribe(), and destroy() methods
  • Uses private symbols to encapsulate internal state
  • Treats objects as atomic entities - any new reference triggers notification

Added: observable.test.js - Comprehensive test suite covering:

  • Value getters and setters
  • Subscriber notifications on value changes
  • Asynchronous notification behavior
  • Multiple subscribers
  • Unsubscribe functionality
  • Clean up and destroy behavior

Key Features

✅ Reactive state management with microtask-based notifications
✅ Strict equality (!==) comparison for change detection
✅ Encapsulated implementation using private symbols
✅ Full test coverage

Testing

All new functionality is covered by unit tests in observable.test.js.

@rflamand rflamand changed the title Add observable files Add observables Jun 24, 2026
@rflamand rflamand marked this pull request as ready for review June 24, 2026 12:22
@rflamand

rflamand commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

@igoroctaviano @fedorov any chance any of you could take a look at this?

@rflamand rflamand force-pushed the feature/raffla/add_observable branch from 396f539 to 2d6e721 Compare July 6, 2026 11:48
@fedorov

fedorov commented Jul 6, 2026

Copy link
Copy Markdown
Member

I will defer to @igoroctaviano!

Igor, please add this to your queue!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new Observable primitive to the codebase to support DOM-independent reactive state, intended as a reusable building block for upcoming work (e.g., observing matchMedia color-gamut changes as discussed in #239).

Changes:

  • Added Observable class implementing async (microtask) subscriber notifications on value replacement.
  • Added unit tests covering core behaviors: get/set, async notification, (un)subscribe semantics, and destroy cleanup.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/observable.js Adds the Observable implementation (value storage, subscribe/unsubscribe, async notification, destroy).
src/observable.test.js Adds Jest tests to validate observable behavior and lifecycle.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/observable.js
Comment on lines +46 to +58
setValue(value) {
const previous = this[_value]
if (value === previous) {
return
}
this[_value] = value
const callbacks = this[_subscribers].slice()
Promise.resolve().then(() => {
for (const cb of callbacks) {
cb(value, previous)
}
})
}
Comment thread src/observable.test.js
expect(() => obs.unsubscribe(() => {})).not.toThrow()
})

it('only removes one instance when the same callback is subscribed once', async () => {
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.

3 participants