-
Notifications
You must be signed in to change notification settings - Fork 16
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
Extensions to the constructor #29
Comments
+1 on the |
One use case for having a default value is for testing "emptiness" Often for shared APIs where a caller can give me any value (including let empty = Symbol('empty')
let context = new AsyncContext("context", empty)
function fn() {
let value = context.get()
if (value === empty) {
throw new Error("Must be inside context") // More specific error
}
if (typeof value === "undefined") {
throw new Error("Context value is undefined")
}
// ...
}
let dict = {}
context.run(dict[nonExistentKey], () => {
fn()
}) |
If name is only for debugging, I think devtools could introduce some magic to automatically get the name from declaration? let foo = new AsyncContext() // magically have the name "foo" |
Not clear why it's footgun?
It's complex to use subclassing to achieve that. We at least need a method/getter (or field?) to make it easy: let x = new class extends AsyncContext { get initValue() { return xxx } } |
That's a good point. It's a little complex to detect whether a value is implicitly undefined, or explicitly undefined, and needs to handle nested calls: class AsyncContextWithDefault {
#count = 0;
#defaultValue;
constructor(defaultValue) {
this.#defaultValue = defaultValue;
}
run(...args) {
try {
this.#count++;
return super.run(...args);
} finally {
this.#count--;
}
}
get() {
if (this.#count === 0) {
return this.#defaultValue;
}
return super.get();
}
} |
Yeah, I really hope we can go back to the early days of JS, and make the language don't differentiate implicitly |
that's been differentiable since the beginning :-) |
I found that Python equivalent API |
I said it can be a foot gun, but it's all about the end user's understanding of shared references in this case. const defaultValue = {
transaction: new Tracing.Transaction({ op: 'logger' })
};
const context = new AsyncContext({ name: 'tracingContext', defaultValue });
function logWithTracing() {
context.run(async () => {
const ctx = context.get();
const id = await getTransactionId(); // do some async stuff
ctx.transaction.setTag('id', id);
await someAsyncOp(ctx.transaction); // do some async stuff
transaction.finish();
});
}
logWithTracing(1);
logWithTracing(2); This would override the |
For the default value, should there be a |
During today's meeting, we decided to accept both
We discussed whether a |
Default would be problematic in the idea I have to track both sides of async operations (resolution side in addition of the subscription side like today). I suppose however that we can always add a |
Can you explain what you mean? I don't understand what resolution and subscription are. |
There are 3 phases to a promise:
I'm interested in learning about context data associated to the resolution phase along the context data of the subscription phase we currently have. However I retract my observation that a default value would be incompatible with my use case, since I expect having to introduce an alternative/extension to |
I've been thinking about 2 extensions to the constructor:
name
stringdefaultValue
valueThe
name
string is intended to aid debugging in dev-tools. I imagine they might want to display the global context mapping, and it'd be more helpful if we could annotate that list in some way. This could be stored on the symbol's description.The
defaultValue
would be returned instead ofundefined
whenever the context hasn't been run in this call stack. This is sometimes useful in React.Originally posted by @jridgewell in #28 (comment)
The text was updated successfully, but these errors were encountered: