-
Notifications
You must be signed in to change notification settings - Fork 30k
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
async_hooks: add bindToAsyncScope method to AsyncResource #33736
Conversation
What's advantage over? asyncResource.runInAsyncScope.bind I guess it saves a some duplication (i.e. don't have to type |
@ronag you're probably right. The main advantage is briefer code. Domains and user-land modules have similar If there will be no voices to have this new method, I'm willing to close this PR. |
If we do not implement this as separate API, I strongly suggest to document We have a similar situation with |
@@ -196,6 +196,13 @@ class AsyncResource { | |||
} | |||
} | |||
|
|||
bindToAsyncScope(fn) { |
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.
The .length
property of the returned function is always 0 here. This may cause problems if the retruned function is used in frameworks like express which use fn.length
to decide which type of handler it is (https://github.com/expressjs/express/blob/master/lib/router/layer.js).
Also properties like Symbol(customPromisifyArgs)
are stripped which may cause problems.
Both issues can be solved by caller but maybe we should at least document it?
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.
We can also set name
and length
to meaningful values before returning the function
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.
Good catch! I'll make sure to address it, if this PR won't be closed.
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.
This is a little magical though... documenting it would be my preference
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.
length
, name
and Symbol(customPromisifyArgs)
are quite easy and most likely harmless if set on wrapped function. The hard part are other properties as they may have special meaning where copy is simply wrong - and not copying either.
@ronag could you elaborate on how the snippet from the PR description would look like with |
req.on('close', asyncResource.runInAsyncScope.bind(asyncResource, () => {
console.log(executionAsyncId()); // Prints the value of `asyncId`.
})); |
@ronag thanks. This snippet seems to be working. Yet, it has one problem: there should be the third argument, as const a = new AsyncResource('foobar');
function foo(bar) {
assert.strictEqual(executionAsyncId(), a.asyncId());
return bar;
}
const ret1 = a.runInAsyncScope.bind(a, foo)('baz');
assert.strictEqual(ret1, 'baz'); // fails
// this one works
const ret2 = a.runInAsyncScope.bind(a, foo, undefined)('baz');
assert.strictEqual(ret2, 'baz'); // passes |
I'm aware of this. Since you were using an arrow function in the example it was not required. |
Makes sense. I'd say that it has to do more with the fact that the snippet contains a no-args function. An arrow function that expects arguments still requires an extra argument in the const ret = a.runInAsyncScope.bind(a, (bar) => {
assert.strictEqual(executionAsyncId(), a.asyncId());
return bar;
})('baz');
assert.strictEqual(ret, 'baz'); // fails Nevertheless, I'm still not sure if this PR brings any value in the light of |
Fwiw that's not entirely comparable, Other than that - I agree with the conclusion and a doc-fix. (I still think it would be very beneficial to provide a one-stop shop to converting an API to promises - though it's less crucial now that the ecosystem has largely migrated to promises already) |
Closing this one in favor of upcoming doc enhancement PR. |
Created the doc enhancement PR: #33751 |
Closes #33723
Adds
bindToAsyncScope()
method toAsyncResource
class. This method should be handy forAsyncLocalStorage
users (and not only them). Say, it allows binding EE/stream listeners to the specific resource:cc @nodejs/async_hooks
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes