My main languages are C and Python. I'm not well versed in JS, and I want to learn clean code development.
Recently, I made a helper function to run some .sql files in a folder. I will put a reduced example here:
const runFiles = async (files) => {
for (const file of files){
const query = fs.readFileSync(file, "utf-8");
await client.query(query);
}
}
Coming from imperative, and usually single-threaded languages, this seems like a natural approach to me. For each file, run query, wait, repeat.
But, I've got a suggestion that the code should be like this:
const runFiles = async (files) => {
Promise.all(files.map(async (file) => {
const query = fs.readFileSync(file, "utf-8");
await client.query(query);
});
}
So I want to ask, to some fellow JS/Node developers here, comparing both versions:
- Is the second one clearer for you over the first one?
- Should I use a functional approach more often?
- Could this be faster? Does it runs in parallel?
Also, can you recommend me a book or resource to learn how to develop clean and modern js?
Top comments (4)
When to use
.map
? When you want to transform the items in the array. That's it. If you want to transform the array in any way, by removing an item or adding one,.map
is not the ideal method. If you just want to loop it's perfectly fine to use afor...of
loop.That said. I think the second example runs faster because you don't wait for each query, they all run concurrently.
Thanks for your feedback, Heiker!
I see now why the second code could run faster. Thinking in a functional way is something I should practice more.
I think it's important to note that the last example is slightly different than the first in that the wrapping function
runFiles
will not actually wait for the promises to resolve. You could always prepend thePromise.all
call with anawait
, but in this instance, I think you might not really needawait
at all. In my experience,await
is just syntactic sugar for Promise chaining. It's only necessary if you need synchronous steps in your asynchronous function. Your example could just be written as this:This gives you some flexibility, because you aren't forcing any Promises to resolve before moving on to the next Promise. In a consuming function, you now have two options.
Wow, many thanks for your reply!
This way of doing things is new to me, and you're opening my eyes to think outside the single threaded box.
I will definitely try this approach, since it's more flexible.