-
Notifications
You must be signed in to change notification settings - Fork 30
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
Suggestion: Consider adding global container object for disposables #41
Comments
I'm sure RxJs would love to see a standardised Disposable (they renamed it to Subscription in v5 but same thing) EDIT: In the RxJs version you can add more cleanups post constructor. Which I have found very useful. So would love to see a similar thing here. // in classes
class SomeService {
disposable = new Disposable();
constructor() {
setupA();
setupB();
}
setupA() {
this.disposable.add(new A());
}
setupB() {
this.disposable.add(new B());
}
dispose() {
this.disposable.dispose();
}
...
} // in React.js
useEffect() => {
let disposable = new Disposable();
disposable.add(stream1
.map(...)
.filter(...)
.subscribe(...)
);
let x = workOutSomethingMidway();
disposable.add(stream2
.flatMap(...)
.delay(...)
.subscribe(...)
);
return () => disposable.dispose();
}, [deps]); |
I'm not sure I want to introduce // in classes
class SomeService {
disposables = [];
constructor() {
setupA();
setupB();
}
setupA() {
this.disposables.push(new A());
}
setupB() {
this.disposables.push(new B());
}
dispose() {
Disposable.from(this.disposables)[Symbol.dispose]();
}
...
} // in React.js
useEffect() => {
let disposables = [];
disposables.push(stream1
.map(...)
.filter(...)
.subscribe(...)
);
let x = workOutSomethingMidway();
disposables.push(stream2
.flatMap(...)
.delay(...)
.subscribe(...)
);
return () => Disposable.from(disposables)[Symbol.dispose]();
}, [deps]); |
Agreed that userland can offer these types of helpers. Mutable disposables with .add and .remove do complicate things, the space for different semantics grows and picking which one is ‘best’ gets more and more subjective. For others reading this thread but not this one. If they want a bit more safety in their useEffect() => {
let cleanupTransferred = false;
let disposables = [];
using const (new Disposable(() => {
if (cleanupTransferred) return;
using const (Disposable.from(disposables))
}));
disposables.push(stream1
.map(...)
.filter(...)
.subscribe(...)
);
let x = workOutSomethingMidway();
disposables.push(stream2
.flatMap(...)
.delay(...)
.subscribe(...)
);
cleanupTransferred = true;
return () => Disposable.from(disposables)[Symbol.dispose]();
}, [deps]); Which could be wrapped up as a userland helper and look like: useEffect() => {
using const subs = new ResourseHelper();
subs.hold(stream1
.map(...)
.filter(...)
.subscribe(...)
);
let x = workOutSomethingMidway();
subs.hold(stream2
.flatMap(...)
.delay(...)
.subscribe(...)
);
return subs.transferToFunction();
}, [deps]); |
I'm considering adding something like the following to the global scope:
These could act as containers to aggregate disposables, guaranteeing that every disposable resource in the container is disposed when the respective disposal method is called. If any disposable in the container throws an error, they would be collected and an
AggregateError
would be thrown at the end.This is a common pattern in several languages that support this feature, and is often used in such things as VS Code extensions:
In addition, if we opt to include a
using value
statement as mentioned here, this would allow us to emulate Go'sdefer
statement:While Go's syntax is more succinct, it doesn't enforce a standard pattern for resource management, which is one of the goals of this proposal.
This would also allow us to support an "async"
defer
-like statement:The text was updated successfully, but these errors were encountered: