-
Notifications
You must be signed in to change notification settings - Fork 29
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
Using with multiple asynchronous resources #16
Comments
Also, huge +1 on pushing this really important idea and concept. |
This scenario is called out in the explainer. Each binding in the async function copy(first, second) {
using(let firstFile = await open(first), otherFile = await open(second)) {
await utils.copyTo(first, second);
}
}
async function copy(first, second) {
using(let firstFile = await open(first)) {
using(let otherFile = await open(second)) {
await utils.copyTo(first, second);
}
}
} |
Thanks, it wasn't clear that it would work with In this case though both files are opened serially which means that if opening a file takes 100ms (just for the example) this example takes 200ms and not 100ms which is what it would take if both would be happening concurrently. If I'm opening 4 resources - the code would take 4 times as long potentially. Is there any way with this proposal to make the resource acquisition concurrent? That was the part that "bought us" when we added |
Also cc @ralt @spion @petkaantonov |
IMO its okay for them not to be parallel You could have a helper function using (let comp = await composite({res1: awaitable1, res2: awaitable2})) {
use comp.res1, comp.res2
} (or another one for arrays) |
@spion writing such a |
Sounds like the proposal handles the use case, and there is nothing to change here, right? |
I think the concern is that the proposed approach still serializes independent allocations. A I've also been considering a disposable container (#13 (comment), basically an Array with a using (const [x, y] = await Promise.using([px, py]) {
} // x and y are disposed because container is disposed |
Precisely @rbuckton, we've found this sort of code to be extremely challenging to write in userland and I think this is something the platform could solve. If in addition to the await using(let x = px, y = py) {
} This way it is somewhat clearer that the await is on all the statements rather than individual ones. The problem is that I'm afraid with the current proposal people will try to do: let px = acquireX();
let py = acquireY();
using(const x = await px, y = await py) {
}
// alternative shed color:
using(x, y) await (getX(), getY()) {
} Which can cause a leak if It is worth mentioning that @spion who was involved in |
Also pinging @1st1 who did this ( |
The proposal has undergone more than a few changes since this issue was opened. The current proposal has reduced scope to only support synchronous We plan to introduce some form of asynchronous async function f() {
const stack = new AsyncDisposableStack();
try {
const res1 = stack.use(new SomeAsyncDisposableResource());
const res2 = stack.use(new SomeOtherAsyncDisposableResource());
...
}
finally {
await stack.disposeAsync(); // async dispose in reverse order.
}
} Unfortunately, the limitation of this approach is that exceptions from async dispose will still shadow any exception from the I will close this issue for now, and will re-open it or move it when the follow-on proposal for async |
Following a suggestion by @littledan to post feedback here - some things we've noticed building and maintaining
Promise.using
for bluebird and discussing the topic:Let's try the absolute simplest case: I want to open two files and copy one to the other. Let's assume an
open
async method, and autils.copy
async method. Let's assume either opening or writing to the file can throw:Now, let's write it with the syntax from this proposal:
This is much nicer syntax! but if I understand correctly in this case if the second
open
rejects the exception is outside the scope of the using (please do correct me if I'm misunderstanding). This means that since the object withSymbol.dispose
didn't get to theusing
yet if one resource was acquired but not yet assigned to the variable declared in that scope.By the way regarding the prior art: Python solves this with the new-ish
async with
syntax. I have asked for the help of the proposal author it for discussing the resource management story for Deno and he agreed to help. I can gladly point him here if you'd like.It is great to see that you have
Symbol.asyncDispose
. I'm not sure how the fs.promises examples work (doesusing
in an async function implicitly await? fs.promise.open returns a promise and not a resource) but would love to collaborate from the Node.js side in order to help.The text was updated successfully, but these errors were encountered: