I quite liked Python's context manager where I did not have to be concerned with how the resource was obtained or cleaned up afterwards. Is there a way to do this in a neat way in Javascript?
Assigning Context Managers to a variable To define the variable, we can use the yield keyword for context manager functions or the return keyword in the __enter__ method for context manager classes.
A context manager usually takes care of setting up some resource, e.g. opening a connection, and automatically handles the clean up when we are done with it. Probably, the most common use case is opening a file. The code above will open the file and will keep it open until we are out of the with statement.
If an error is raised in __init__ or __enter__ then the code block is never executed and __exit__ is not called. Once the code block is entered, __exit__ is always called, even if an exception is raised in the code block.
You can make something similar using generator functions in javascript:
function* usingGroup() {
// setup
console.group()
try {
yield
} finally {
// cleanup
console.groupEnd()
}
}
and to use it, you can use a for ... of
loop:
for(const _ of usingGroup()) {
console.log('inside a group')
}
This method is similar to how you define context managers in python using the @contextmanager
decorator. Although the way of using a for loop to define where the context applies feels strange in my opinion.
How does it work:
Abstracting away the whole generator object and iterator protocol, you can think of it as doing this: before the first iteration of the loop, the code inside the generator function is run until the yield
statement, at this point, the for loop body runs once since a value has been yielded by the generator, before the next iteration, the rest of the code in the generator is run. Since it does not yield, the loop considers it done and exits without executing its body again. The try ... finally
ensures that even if an error is thrown, the code gets executed.
If you need to use some value inside your loop (like a file you opened for example), you can just yield
it inside the generator.
full code:
function* usingGroup() {
console.group()
try {
yield
} finally {
console.groupEnd()
}
}
for(const _ of usingGroup()) {
console.log('inside a group')
}
I also surprised by missing this feature. Unfortunately, only callback based solutions are available in JS
https://promise-nuggets.github.io/articles/21-context-managers-transactions.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With