Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any tips on context manager similar to Python in Javascript?

Tags:

javascript

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?

like image 314
jiminssy Avatar asked Jul 13 '20 15:07

jiminssy


People also ask

Which Python keyword is used for context management?

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.

When would you use a context manager?

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.

Is __ exit __ always called?

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.


2 Answers

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')
}
like image 140
Thetos Avatar answered Oct 20 '22 15:10

Thetos


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

like image 3
kmmbvnr Avatar answered Oct 20 '22 17:10

kmmbvnr