<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Florian Lackner</title>
    <description>The latest articles on DEV Community by Florian Lackner (@florian_lackner_dde2cd598).</description>
    <link>https://dev.to/florian_lackner_dde2cd598</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3576876%2F2f021946-59a7-462d-8215-2183aed4354a.jpg</url>
      <title>DEV Community: Florian Lackner</title>
      <link>https://dev.to/florian_lackner_dde2cd598</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/florian_lackner_dde2cd598"/>
    <language>en</language>
    <item>
      <title>Things I learned picking up a new language as an adult</title>
      <dc:creator>Florian Lackner</dc:creator>
      <pubDate>Tue, 21 Oct 2025 12:33:57 +0000</pubDate>
      <link>https://dev.to/365talents/things-i-learned-picking-up-a-new-language-as-an-adult-52f6</link>
      <guid>https://dev.to/365talents/things-i-learned-picking-up-a-new-language-as-an-adult-52f6</guid>
      <description>&lt;p&gt;Since I came to France six months ago, I have made a lot of progress with the French language. What started as nearly incomprehensible stuttering are now full phrases with rich vocabulary and even one little joke here and there. I've made picking up French my personal project, and it brings a lot of joy in my life. Understanding people in more and more contexts is enriching and helps with the struggles every expat experiences being far from home.&lt;/p&gt;

&lt;p&gt;I recently stumbled across &lt;a href="https://youtu.be/d0yGdNEWdn0" rel="noopener noreferrer"&gt;a talk by Chris Lonsdale&lt;/a&gt; from nearly ten years ago, where he talks about his experience learning languages. I highly recommend watching it if you haven't already. It resonated so well with me that it inspired me to write this blog post. He claims anybody can be fluent in a new language in six months. It sounds crazy, but having tried that myself, I believe he is right.&lt;/p&gt;

&lt;p&gt;In his presentation, Chris claims that there are five basic principles you can apply and seven simple actions you can perform to boost your language skills massively. I will repeat them here and add my own comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five basic principles
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Focus on language content that is relevant to you.
&lt;/h3&gt;

&lt;p&gt;I agree with him here. I still have unpleasant memories of high school times were we were forced to study rather obscure books in French, which included weird vocabulary and uninteresting stories. It was hell. It is so much harder to remember irrelevant information than interesting information that it becomes quickly frustrating.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use your new language as a tool to communicate.
&lt;/h3&gt;

&lt;p&gt;I guess the key take-away here is to &lt;strong&gt;use&lt;/strong&gt; a language. If you want to convey some meaning, at least in Europe, you can always fall back to English. This is even possible in France, contrary to popular belief.&lt;/p&gt;

&lt;p&gt;But you shouldn't use this escape hatch. Using a language takes practice you'll never get if you're not training. All beginnings will be hard, but ultimately you will progress, and that's what counts. Every little piece of information you communicate is a major win and should be treated as such. Feeling insecure about your level in a language is only going to hold you back.&lt;/p&gt;

&lt;p&gt;I did a thought experiment one day to deal with this insecurity: I put myself into the other person's position and imagined a situation where I was talking to a person barely able to speak German (my native language). No matter how badly the person speaks, I would never consider their effort anything less than exactly that: a nice effort. In my opinion, it's remarkable if foreigners know your language, be it only so little. I think that the vast majority of people think of it that way. So why was I even embarrassed in the first place?&lt;/p&gt;

&lt;h4&gt;
  
  
  3. When you first understand the message, you will unconsciously acquire the language.
&lt;/h4&gt;

&lt;p&gt;NEVER LEARN GRAMMAR. EVER.&lt;/p&gt;

&lt;p&gt;In serious terms, you should always focus on the message. The rest follows naturally. Learning grammar is the exact opposite. You focus on the language's syntax by trying to learn and apply logical rules. That's how a computer might try to approach learning a language, but for humans, this is a dead-end.&lt;/p&gt;

&lt;p&gt;In fact, have you ever noticed how native speakers of any language do not know grammar rules while applying them correctly 100% of the time? The most extreme example is children. They have never heard of grammar but speak as error-free as their parents. When asking them why they use this or that grammatical construction, they cannot give a better answer than: "Because that's how it is."&lt;/p&gt;

&lt;p&gt;I believe that our brain is naturally "optimized" to find and internalize these rules subconsciously. This way, we can apply them with lightning speed and astonishing correctness without even thinking about them.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Language learning is physiological training.
&lt;/h3&gt;

&lt;p&gt;This might be new to many. Chris tells the story of a Taiwanese woman who excelled in English in school but utterly failed to understand English spoken by native speakers once confronted with it. The idea is that our ears, i.e., our brains, need to learn to hear foreign sounds.&lt;/p&gt;

&lt;p&gt;My favorite example of this is the four types of "tch" sounds in the &lt;a href="https://www.britannica.com/topic/Bosnian-Croatian-Montenegrin-Serbian-language" rel="noopener noreferrer"&gt;Bosnian-Croatian-Montenegrin-Serbian language&lt;/a&gt;. There are two pairs: č / ć and dž / đ. You can find more information (including hearing samples) &lt;a href="https://www.letslearncroatian.co.uk/blog/the-croatian-letters" rel="noopener noreferrer"&gt;here&lt;/a&gt;. It is nearly impossible to hear the differences for me, how about you?&lt;/p&gt;

&lt;p&gt;The same argument also applies to speaking. It takes muscles to do, and different languages use different movements of these muscles. We can train these movements like athletes do in sports. I witnessed a massive improvement in my ability to say certain French words after a couple of months. Initially, it felt like my tongue was somehow tied to a knot when attempting them. This feeling vanishes more and more every day. And if I think about it in retrospect, it really is similar to the clumsy feeling when picking up a new sport. Or when taking first dance lessons.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Psycho-physiological state matters.
&lt;/h3&gt;

&lt;p&gt;This is a no-brainer on the one hand, but on the other hand, it's easy to forget about. If your brain is busy with other things, you won't learn. Especially important is staying relaxed when you don't understand something. It's normal, and being angry about it is as pointless as it is hindering your learning efforts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The seven actions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Listen a lot.
&lt;/h3&gt;

&lt;p&gt;Obvious and still often overlooked. You can basically soak your mind in a language. I think it's not necessary to listen actively all the time. A radio in the background also helps. Your brain will get used to the language this way.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Focus on getting the meaning first.
&lt;/h3&gt;

&lt;p&gt;I wholeheartedly agree. Sometimes, I catch myself obsessing over single words and their meaning. While thinking about it, I lose context and I stop understanding most of what is said.&lt;/p&gt;

&lt;p&gt;Another aspect is body language. It is actually different in most countries and conveys so much meaning. This is especially visible in Italy, the capital of expressive body language, in my opinion, but it applies everywhere.&lt;/p&gt;

&lt;p&gt;And one last thing: We can use things we already know. For example, French shares a lot of its vocabulary with English. I use this a lot to guess the meaning of new words in French, and it works way better than it should.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Start mixing.
&lt;/h3&gt;

&lt;p&gt;The call to action here is to be creative. Try new combinations of words, try to invent new expressions, etc. Babies, my great role models in language learning, talk like this.&lt;/p&gt;

&lt;p&gt;In my experience, the outcome conveys its meaning while also sounding funny to natives. So, you've basically cracked a joke in a foreign language; congratulations. In essence, whatever works is fine and should be used.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Focus on the core.
&lt;/h3&gt;

&lt;p&gt;Chris presents some statistics here. He claims that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;1000 words cover 85% of what you say on a daily basis.&lt;/p&gt;

&lt;p&gt;3000 words cover 95% of what you say on a daily basis.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If it is true, this is way less than I thought. Three thousand words does not sound impossible; quite the contrary. And if you can say 95% of what you want to say in your daily life one could argue that you speak the language.&lt;/p&gt;

&lt;p&gt;A sub-advice he gives is to focus on your "toolbox" of words. This means phrases like "What is this?" ("Qu'est-ce que c'est ?" in French, believe it or not), "What does this mean?", etc. This gives an excellent foundation and enables you to communicate and learn much quicker because you don't need to leave the language to ask these questions — Big recommendation from me as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Get yourself a language parent.
&lt;/h3&gt;

&lt;p&gt;Chris uses the word parent to hint that babies learn languages this way. One could also say a mentor. A mentor should be a person that is genuinely interested in you as a person and somebody who helps you to communicate. The goal is a safe environment where you can speak comfortably. He claims this concept is successful as it is used by billions of parents all over the world, and all of their kids are able to speak in the end — A convincing argument for me.&lt;/p&gt;

&lt;p&gt;I totally agree with this one. I had several mentors throughout my French adventure, and it is the biggest boost for language learning, in my opinion. One of my mentors was a good French friend with whom I started speaking only in French from the day I moved there.&lt;/p&gt;

&lt;p&gt;It was hard initially, but he did not get tired of helping me out when I was looking for words, and my proficiency in French increased noticeably every week. There are many ways to find these mentors: friends, online dating, sports clubs, work colleagues; you name it.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Copy the face.
&lt;/h3&gt;

&lt;p&gt;This supposedly makes it easier to copy the native accent. I tried this once in high school to fake a British accent, and it really worked. I have yet to do more experiments, but it's an interesting idea I will pursue further.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Directly connect to mental images.
&lt;/h3&gt;

&lt;p&gt;Don't translate from one language into another in your head. Connect the idea, the image, the feeling directly to the word in the new language, like it is connected to the word in your native language.&lt;/p&gt;

&lt;p&gt;This is great advice and also one of the many mistakes made by schools over and over. Vocabulary lists are one negative example. They incentivize translating in your head, among other problems they have.&lt;/p&gt;

&lt;p&gt;In my experience, it is a habit to translate in the head. The same is true for actively doing the exact opposite. I'm trying to make it a habit to connect the words directly to the ideas they represent, and I'm seeing two benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The respective words started popping into my mind whenever I saw something or thought about an abstract idea.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I started to have a feeling about when which word is appropriate. Many words have very similar meanings, like walking and marching in English. Still, there is a difference; sometimes, you can't use one where you can use the other. I'm sure there is always an explanation / a rule for these cases, but that doesn't help when you're in the middle of saying a sentence. The feeling is instantaneous and almost always right, so go for it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Chris' talk was eye-opening for me. It put into words better than I ever could many vague feelings I had about language learning in these past couple of months. Of all the tips he gave, I like the one with the mentor best. It has helped me a lot with French while also being very nice from a social perspective. If you take one of the ideas presented here home, make it this one.&lt;/p&gt;

</description>
      <category>french</category>
    </item>
    <item>
      <title>Why do we need async/await in JavaScript?</title>
      <dc:creator>Florian Lackner</dc:creator>
      <pubDate>Tue, 21 Oct 2025 12:32:19 +0000</pubDate>
      <link>https://dev.to/365talents/why-do-we-need-asyncawait-in-javascript-37fe</link>
      <guid>https://dev.to/365talents/why-do-we-need-asyncawait-in-javascript-37fe</guid>
      <description>&lt;p&gt;&lt;em&gt;First posted &lt;a href="//www.lackner.work/posts/2025/03/01/why-do-we-need-async-await-in-js/"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Async/await is a major source of confusion in JavaScript. People tend just to add and remove the &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; keywords until the code works (or seems to work). In this article, I want to explain what async/await actually means by developing the concept from vanilla, &lt;em&gt;synchronous&lt;/em&gt; JavaScript to asynchronous JavaScript with the async/await syntax sugar. It is my personal take on the subject. I hope some will find it interesting.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: I use Node.js as an example of a JavaScript runtime in this article. However, what's discussed also applies to other runtimes like web browser JS engines. All these environments follow similar architectures.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem does it solve?
&lt;/h2&gt;

&lt;p&gt;Suppose you have a function that does some I/O.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;doDatabaseQuery&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;doElasticsearchQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readMyFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we assume that the query functions and the &lt;code&gt;readMyFile&lt;/code&gt; function will block the JavaScript code while they perform their I/O. Eventually,  it will be done, and we can continue where we left off. They will signal an error by throwing. We handle it with a &lt;code&gt;try/catch&lt;/code&gt; block.&lt;/p&gt;

&lt;p&gt;Doing database queries or other I/O like network requests or filesystem operations takes a very long time™ compared to running your JavaScript code. This is fine in this example if we look at a single request/response. But web servers usually handle thousands of requests. And then this model breaks. To understand why we have to look at how Node.js runs your JS code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Node.js has a single-threaded event loop
&lt;/h2&gt;

&lt;p&gt;Node.js runs all your JS code in a single thread. &lt;a href="http://book.mixu.net/node/ch2.html" rel="noopener noreferrer"&gt;The exact reasoning&lt;/a&gt; behind this design choice is fascinating but out of scope for this article. In my opinion, the two most compelling arguments in favor of Node's architecture are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The other option would be to use concurrent threads. This comes with many complexity hazards like synchronization, deadlocks, etc. In this sense, Node's model is simpler.&lt;/li&gt;
&lt;li&gt;It turns out that I/O heavy applications like web servers tend to &lt;strong&gt;wait&lt;/strong&gt; a lot. And by that, I mean &lt;strong&gt;a lot&lt;/strong&gt;. They do nothing else, basically. The heavy lifting usually happens outside the web server, in a database, in elastic search, you name it. The web server just requests the data, waits for it, and glues it together to send it back to the client. So having several threads will not make your code more performant because its performance is not CPU-bound.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, while JS code runs sequentially, we can still work on many requests simultaneously. For example, you can start your washing machine, dishwasher, and microwave one after another and then wait for them to finish their respective tasks. You can do the same with requests to your database, elastic search, etc.&lt;/p&gt;

&lt;p&gt;The big question is: &lt;strong&gt;How can we wait without blocking?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Callbacks
&lt;/h2&gt;

&lt;p&gt;So code running in Node is not supposed to stop executing to wait for something external to be done. But we often need to do something &lt;strong&gt;after&lt;/strong&gt; say, a network request was completed. The way this is handled is straightforward: We give the runtime a function to call after it performed our I/O operation with its result. This function is called a callback function. We can see how the example would look like using callbacks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;doDatabaseQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// first callback&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;doElasticsearchQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// second callback&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nf"&gt;readMyFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// third callback&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nf"&gt;sendToClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// strawman function to send a response to the client&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The I/O functions take a second argument this time, the callback. Note that we couldn't just return our result in this case. When &lt;code&gt;handleRequest&lt;/code&gt; runs it will call &lt;code&gt;doDatabaseQuery&lt;/code&gt; and then it will return &lt;strong&gt;immediately&lt;/strong&gt;. The Node.js runtime will later call the callback, which will call &lt;code&gt;doElasticsearchQuery&lt;/code&gt;. The callback also returns quickly. It will call only &lt;code&gt;readMyFile&lt;/code&gt; with another callback which will finally call &lt;code&gt;sendToClient&lt;/code&gt; to finish our request once the file was read. We returned &lt;code&gt;result&lt;/code&gt; in the original example. This is impossible with callbacks, so we're using this strawman function &lt;code&gt;sendToClient&lt;/code&gt; that sends the response back to the client.&lt;/p&gt;

&lt;p&gt;Error handling is explicit in this model. By convention, the first argument of the callback function is an error object. If it is not &lt;code&gt;undefined&lt;/code&gt;, something went wrong, and we can handle it in the callback. The second argument is, by convention, the result of the I/O operation. There are other styles, but they all boil down to the same idea: The error is communicated via some error argument to the callback.&lt;/p&gt;

&lt;p&gt;This is the way Node.js handles I/O. Many will rightfully argue that the code looks messier than initially. The code tends to get more and more unreadable if the nesting of the callbacks becomes too deep. And error handling makes things even worse. This problem is referred to as &lt;a href="https://medium.com/techfront/javascript-callback-hell-simply-explained-93c3cf4be884" rel="noopener noreferrer"&gt;callback hell&lt;/a&gt;. Several abstractions over callbacks have been developed to deal with this. The most widely used one is called &lt;code&gt;Promise&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Promises
&lt;/h2&gt;

&lt;p&gt;The idea of an asynchronous function not returning its result contributes greatly to the unreadability of callback-spaghetti-code. Promises fix this by letting an asynchronous function return something again. But because asynchronous functions still can't block, it can't be the actual value. Instead, they return a &lt;code&gt;Promise&lt;/code&gt;, which can be interpreted as: "I promise that the value will eventually be here." The jargon is: "The promise resolves to the value". So this time, the I/O functions return promises that resolve to their respective values.&lt;/p&gt;

&lt;p&gt;Furthermore, promises simplify error handling by splitting the error handling logic from the business logic. Instead of getting the error in the callback, you can register a dedicated error callback, which gets called instead of the normal callback if there is an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;doDatabaseQuery&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;dataPromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileNamePromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dataPromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// first callback&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileNamePromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;doElasticsearchQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fileNamePromise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;fileNamePromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileNamePromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// second callback&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readMyFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;resultPromise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;resultPromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;resultPromise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cool thing about promises is that they are designed to be &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#chaining" rel="noopener noreferrer"&gt;chained&lt;/a&gt;. You can add callbacks to a promise chain with &lt;code&gt;then(callback)&lt;/code&gt;. The result is again a promise that resolves to the return value of the callback given to &lt;code&gt;then()&lt;/code&gt;. If the callback returns another &lt;code&gt;Promise&lt;/code&gt;, the promise returned by &lt;code&gt;then&lt;/code&gt; will not resolve to this other &lt;code&gt;Promise&lt;/code&gt;, but the value it resolved to. This enables chaining. And chaining avoids the deep nesting of pure callback approaches. Also, we can return something from &lt;code&gt;handleRequest&lt;/code&gt; again. This time it's a &lt;code&gt;Promise&lt;/code&gt; that resolves to &lt;code&gt;result&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Chaining also works for errors! You can add an error callback with &lt;code&gt;catch(callback)&lt;/code&gt;. If an operation fails the &lt;strong&gt;closest&lt;/strong&gt; error callback will be called. This helps a lot in our example because all our error handling code is the same.&lt;/p&gt;

&lt;p&gt;We can write our example more elegantly. Firstly, we can eliminate the repetitive error handling and add the error handler only once. Secondly, we can use our I/O functions and the error handler directly as callbacks. This works because, e.g., the first callback in the code snippet takes data and returns a &lt;code&gt;Promise&lt;/code&gt; resolving to &lt;code&gt;fileName&lt;/code&gt;. This is exactly what &lt;code&gt;doElasticsearchQuery&lt;/code&gt; is doing, which is why we can use it directly as an argument to &lt;code&gt;then&lt;/code&gt;. We can do similarly for &lt;code&gt;readMyFile&lt;/code&gt; and &lt;code&gt;handleError&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;doDatabaseQuery&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doElasticsearchQuery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;readMyFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Promises have already helped tremendously in cutting down the complexity of callbacks. However, the resulting code is still a bit weird and not as clear as the synchronous equivalent. This is why &lt;code&gt;async/await&lt;/code&gt; (and &lt;code&gt;try/catch&lt;/code&gt; in &lt;code&gt;async&lt;/code&gt; contexts) has been added to JavaScript!&lt;/p&gt;

&lt;h2&gt;
  
  
  async/await
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;async/await&lt;/code&gt; is so-called syntax sugar for promises. This means it gets compiled to promises by the JavaScript compiler before executing the code. And remember, promises are callbacks under the hood. Nothing magical about these things. So here is the example written with &lt;code&gt;async/await&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;doDatabaseQuery&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;doElasticsearchQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;readMyFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it looks very similar to the initial synchronous example. But actually, it is &lt;strong&gt;identical&lt;/strong&gt; to the &lt;code&gt;Promise&lt;/code&gt; version. This means you could replace the &lt;code&gt;Promise&lt;/code&gt; version with this code and get the exact same function. Let's look at the differences to the initial synchronous example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;handleRequest&lt;/code&gt; became an &lt;code&gt;async function&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use of the &lt;code&gt;await&lt;/code&gt; keyword in front of the I/O functions. Even though they return promises, &lt;code&gt;await&lt;/code&gt; turns those into the values they resolve to.&lt;/li&gt;
&lt;li&gt;We return &lt;code&gt;result&lt;/code&gt; directly. However, &lt;code&gt;handleRequest&lt;/code&gt; will still return a &lt;code&gt;Promise&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;async&lt;/code&gt; will turn a &lt;code&gt;function&lt;/code&gt; into an &lt;code&gt;async function&lt;/code&gt;. This has two effects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can use &lt;code&gt;await&lt;/code&gt; inside of &lt;code&gt;async&lt;/code&gt; functions. Outside of them, you can't.&lt;/li&gt;
&lt;li&gt;The return value of an &lt;code&gt;async&lt;/code&gt; function is a &lt;code&gt;Promise&lt;/code&gt; resolving to the value returned by the &lt;code&gt;async function&lt;/code&gt;. Even if you don't explicitly return your &lt;code&gt;async function&lt;/code&gt; will return a &lt;code&gt;Promise&lt;/code&gt; that resolves to &lt;code&gt;undefined&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;await&lt;/code&gt; can only be used inside &lt;code&gt;async&lt;/code&gt; functions (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await" rel="noopener noreferrer"&gt;and JavaScript modules&lt;/a&gt;). It takes a &lt;code&gt;Promise&lt;/code&gt; and turns it into the value it resolves to. It "waits" for value to be ready.&lt;/p&gt;

&lt;p&gt;Furthermore, if there was an error and the &lt;code&gt;Promise&lt;/code&gt; had no error callback attached, &lt;code&gt;await&lt;/code&gt; will &lt;code&gt;throw&lt;/code&gt; the error object that would have been passed as argument to the error callback. This makes error handling with &lt;code&gt;try/catch&lt;/code&gt; easy and convenient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapup
&lt;/h2&gt;

&lt;p&gt;I hope this showed how &lt;code&gt;async/await&lt;/code&gt; fits into the I/O story for Node.js and JavaScript in general. It's just syntactic sugar for promises, which are themselves an abstraction over callbacks. This article just touches on the basics, though. I deliberately omitted important pieces of the puzzle, like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" rel="noopener noreferrer"&gt;error handling with promises&lt;/a&gt;, to keep it simple.&lt;/p&gt;

&lt;p&gt;As a bonus, I will give some async functions and their identical twins implemented with Promises to show how the code is transformed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// resolve returns a promise that calls its callback immediately&lt;/span&gt;
  &lt;span class="c1"&gt;// with the value x. i.e. a promise that is immediately "ready"&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nothing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// empty body&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nothing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;myFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fetch error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;myFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fetch error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parallelFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promises&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// both fetches are being performed simultaneously in the background&lt;/span&gt;
  &lt;span class="c1"&gt;// (outside of the event loop, parallel to this code)&lt;/span&gt;

  &lt;span class="c1"&gt;// new promise that resolves when all given promises have resolved&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bundlePromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// this will wait until both fetches are done&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;resultX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultY&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bundlePromise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resultX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultY&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parallelFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promises&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bundlePromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;bundlePromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;resultX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultY&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resultX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultY&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Dates in JS</title>
      <dc:creator>Florian Lackner</dc:creator>
      <pubDate>Tue, 21 Oct 2025 07:23:30 +0000</pubDate>
      <link>https://dev.to/365talents/dates-in-js-300d</link>
      <guid>https://dev.to/365talents/dates-in-js-300d</guid>
      <description>&lt;p&gt;&lt;em&gt;First posted &lt;a href="https://www.lackner.work/posts/2025/10/21/dates-in-js/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Date and time handling is arguably one of the most complicated things in computer science. It seems simple, since everybody knows how to read a clock or how to use a calendar. But the devil is in the details, as always. Since so many people seem to get it wrong &lt;a href="https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time" rel="noopener noreferrer"&gt;over&lt;/a&gt; and &lt;a href="https://infiniteundo.com/post/25509354022/more-falsehoods-programmers-believe-about-time" rel="noopener noreferrer"&gt;over&lt;/a&gt;, we should talk about it.&lt;/p&gt;

&lt;p&gt;In this blog post I want to offer a mental model to you. It created this famous &lt;em&gt;click&lt;/em&gt; moment for me. Maybe it helps you too. Let me know, I'd be delighted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terminology
&lt;/h3&gt;

&lt;p&gt;Let's give clearly defined names to the things we'll talk about. The topic is already complicated enough without confusion induced by the ambiguous nature of human language.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;code&gt;Date&lt;/code&gt; is the information you can find on a physical calendar. It's a day, month and year.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;Time&lt;/code&gt; is the information you can find on a wall clock. It's an hour, minute and second. You can of course go finer by giving milliseconds etc.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;DateTime&lt;/code&gt; is a &lt;code&gt;Date&lt;/code&gt; and a &lt;code&gt;Time&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;Instant&lt;/code&gt; is a point in time on the planet. If two &lt;code&gt;Instant&lt;/code&gt;s are the same, this means that they happened at the same moment, physically speaking.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;Timezone&lt;/code&gt; is an algorithm to convert an &lt;code&gt;Instant&lt;/code&gt; to a &lt;code&gt;DateTime&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The key takeaway
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A &lt;code&gt;DateTime&lt;/code&gt; is NOT an &lt;code&gt;Instant&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you take one thing home today, it should be this. &lt;strong&gt;A &lt;code&gt;DateTime&lt;/code&gt; is NOT an &lt;code&gt;Instant&lt;/code&gt;.&lt;/strong&gt; Neither can you convert between the two losslessly. They are fundamentally different concepts. In my opinion the confusion between the two is the cause of most bugs in date and time handling.&lt;/p&gt;

&lt;p&gt;The mental model I'm offering is that these are different things that can't be converted without loss of information. You need to ask yourself &lt;em&gt;every time&lt;/em&gt; which of the two you're working with and you can't mix and match them.&lt;/p&gt;

&lt;p&gt;Let's use an example to show the difference. Say you're speaking on the phone with a friend who lives on the other side of the planet. Where you live it's maybe the evening, while your friend's about to start their day. Your &lt;code&gt;DateTime&lt;/code&gt; is very different from your friend's &lt;code&gt;DateTime&lt;/code&gt;. Yet, you're having a conversation at the same &lt;code&gt;Instant&lt;/code&gt; in time. Of course, because you're saying something and your friend responds immediately (ignoring the slight delay imposed by the speed of light).&lt;/p&gt;

&lt;p&gt;So let's repeat this again. &lt;strong&gt;A &lt;code&gt;DateTime&lt;/code&gt; is NOT an &lt;code&gt;Instant&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Timezones
&lt;/h3&gt;

&lt;p&gt;Let's take the example further. Say you didn't have your conversation yet. Since you and your friend are both busy, you schedule it. Easy, you agree on an &lt;code&gt;Instant&lt;/code&gt; in the future and be done with it. While it's true that you must agree on an &lt;code&gt;Instant&lt;/code&gt;, it's unfortunately also true that people don't work on &lt;code&gt;Instant&lt;/code&gt;s. They work on &lt;code&gt;DateTime&lt;/code&gt;s. How impractical. And since your friend lives far away, the &lt;code&gt;DateTime&lt;/code&gt;s for the &lt;code&gt;Instant&lt;/code&gt; of your call won't be the same.&lt;/p&gt;

&lt;p&gt;You need to convert the &lt;code&gt;Instant&lt;/code&gt; to a &lt;code&gt;DateTime&lt;/code&gt; for each one of you. The algorithm to do so is called a &lt;code&gt;Timezone&lt;/code&gt;. I'm saying algorithm, because &lt;code&gt;Timezone&lt;/code&gt;s are more than just a simple offset. There are complications like daylight saving time, leap seconds, and historical changes in time zones. I'd consider them black box algorithms, because they're complex and there's no shortcut around this fact.&lt;/p&gt;

&lt;p&gt;Say you're living in France. Your &lt;code&gt;Timezone&lt;/code&gt; is called "Central European Time" (&lt;code&gt;CET&lt;/code&gt;) or &lt;code&gt;Europe/Paris&lt;/code&gt;. Your friend lives in India. Their &lt;code&gt;Timezone&lt;/code&gt; is called "Indian Standard Time" (&lt;code&gt;IST&lt;/code&gt;) or &lt;code&gt;Asia/Kolkata&lt;/code&gt;. You both agree on an &lt;code&gt;Instant&lt;/code&gt; in the future. Then, you need to apply the respective &lt;code&gt;Timezone&lt;/code&gt;s to the same &lt;code&gt;Instant&lt;/code&gt; to get your &lt;code&gt;DateTime&lt;/code&gt;s. I've used India as an example, because its &lt;code&gt;Timezone&lt;/code&gt; doesn't experience daylight saving time. In France, however, it does. So the way to calculate the &lt;code&gt;DateTime&lt;/code&gt;s in each case are very different.&lt;/p&gt;

&lt;h3&gt;
  
  
  Universal Time Code (UTC)
&lt;/h3&gt;

&lt;p&gt;The keyword "UTC" comes up a lot in discussions around time management. It is the name of a &lt;code&gt;Timezone&lt;/code&gt; called "Universal Time Code". It is very often used to communicate &lt;code&gt;Instant&lt;/code&gt;s between actors in different &lt;code&gt;Timezone&lt;/code&gt;s. It has a special property that makes it very useful for storing &lt;code&gt;Instant&lt;/code&gt;s. It doesn't experience daylight saving time. This means that the conversion between &lt;code&gt;Instant&lt;/code&gt;s and &lt;code&gt;DateTime&lt;/code&gt;s becomes reversible. Or in other words: &lt;strong&gt;A &lt;code&gt;DateTime&lt;/code&gt; in &lt;code&gt;UTC&lt;/code&gt; is equivalent to an &lt;code&gt;Instant&lt;/code&gt;&lt;/strong&gt;. You can convert between the two without loss of information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storage
&lt;/h3&gt;

&lt;p&gt;So how do you store &lt;code&gt;Instant&lt;/code&gt;, &lt;code&gt;DateTime&lt;/code&gt; and &lt;code&gt;Timezone&lt;/code&gt; ?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Instant&lt;/code&gt;s can be stored as offset from a known &lt;code&gt;Instant&lt;/code&gt; (epoch) in seconds. This is also called a timestamp. A common choice of the epoch is the &lt;code&gt;Instant&lt;/code&gt; that corresponds to the &lt;code&gt;DateTime&lt;/code&gt; Jan 1st 1970 at midnight in the &lt;code&gt;Timezone&lt;/code&gt; UTC. The offset can be in seconds, milliseconds, etc. You can choose the granularity. This storage method is space efficient, since you only need to store one number.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DateTime&lt;/code&gt;s can be stored as strings or as &lt;code&gt;Instant&lt;/code&gt; in &lt;code&gt;UTC&lt;/code&gt;. There are several formats for the string representation. The most common format is the &lt;a href="https://en.wikipedia.org/wiki/ISO_8601" rel="noopener noreferrer"&gt;ISO 8601 format&lt;/a&gt;. It looks like this: &lt;code&gt;2023-03-15T12:34:56&lt;/code&gt;. This corresponds to March 15th, 2023 at 12:34:56. The &lt;code&gt;Timezone&lt;/code&gt; is not specified in this example.&lt;/p&gt;

&lt;p&gt;The second storage method is to store &lt;code&gt;DateTime&lt;/code&gt;s as &lt;code&gt;Instant&lt;/code&gt;s in &lt;code&gt;UTC&lt;/code&gt;. As already discussed, &lt;code&gt;Instant&lt;/code&gt;s in &lt;code&gt;UTC&lt;/code&gt; map uniquely to &lt;code&gt;DateTime&lt;/code&gt;s and vice-versa. This storage method is space efficient, since you only need to store one number. However, it is important to note that it is easy to make mistakes when using this method. You have to be very careful with your conversions.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Timezone&lt;/code&gt; values are usually stored as strings. There are standardized names for timezones. You should use these names. They are supported by libraries implementing &lt;code&gt;Timezone&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;DateTime&lt;/code&gt; or &lt;code&gt;Instant&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Let's do some examples of when to use which for your information.&lt;/p&gt;

&lt;p&gt;The time information of a log entry in a computer system: &lt;code&gt;Instant&lt;/code&gt;, because it happens at a specific point in time.&lt;/p&gt;

&lt;p&gt;Showing an &lt;code&gt;Instant&lt;/code&gt; to a user: &lt;code&gt;DateTime&lt;/code&gt; (obtained by applying the users &lt;code&gt;Timezone&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;A users birthdate: &lt;code&gt;Date&lt;/code&gt; / &lt;code&gt;DateTime&lt;/code&gt; , because that's what's written on their official documents.&lt;/p&gt;

&lt;p&gt;The timing information of a one-off calendar event in a shared calendar: &lt;code&gt;Instant&lt;/code&gt;, because it happens at a specific point in time. The &lt;code&gt;Timezone&lt;/code&gt; of one user does not influence the &lt;code&gt;Instant&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The timing information of a recurring calendar event. That's a tricky one. Think of every Monday at 2AM. What happens if the user changes their timezone? What happens on the day the clocks are reset for daylight saving time? Does the event happen twice? In my opinion there's no absolute answer here. It depends on how you want your system to behave. I'd store a &lt;code&gt;DateTime&lt;/code&gt; + &lt;code&gt;Timezone&lt;/code&gt;. I'd add code to handle the edge cases of the &lt;code&gt;Timezone&lt;/code&gt; (using a library of course). And then I'd start praying.&lt;/p&gt;

&lt;h3&gt;
  
  
  The JS &lt;code&gt;Date&lt;/code&gt; class
&lt;/h3&gt;

&lt;p&gt;So what does the JS &lt;code&gt;Date&lt;/code&gt; class represent? It's JS, so let's not be surprised by the answer: &lt;strong&gt;an &lt;code&gt;Instant&lt;/code&gt;.&lt;/strong&gt; Yes, that's the hard truth. And I want to be very clear: There is no &lt;code&gt;Timezone&lt;/code&gt; information stored in the &lt;code&gt;Date&lt;/code&gt; class. No &lt;code&gt;UTC&lt;/code&gt;. It's an &lt;code&gt;Instant&lt;/code&gt;. End of story.&lt;/p&gt;

&lt;p&gt;But why does it have getters and setters for years, months, days, hours, minutes, and seconds? Because it's badly designed. And what do these return? They convert the &lt;code&gt;Instant&lt;/code&gt; to a &lt;code&gt;DateTime&lt;/code&gt; in the local &lt;code&gt;Timezone&lt;/code&gt; of your user (frontend) or your server (backend). And then they extract the year, month, etc. and return them as numbers.&lt;/p&gt;

&lt;p&gt;And here's another hard truth: Your users &lt;code&gt;Timezone&lt;/code&gt; might be &lt;strong&gt;anything&lt;/strong&gt;. You can't assume that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;it's correct.&lt;/li&gt;
&lt;li&gt;it does / doesn't experience daylight saving time&lt;/li&gt;
&lt;li&gt;its offset to &lt;code&gt;UTC&lt;/code&gt; is positive / negative&lt;/li&gt;
&lt;li&gt;it won't change&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You need to code with this in mind.&lt;/p&gt;

&lt;p&gt;I think the JS &lt;code&gt;Date&lt;/code&gt; class should be avoided for anything related to &lt;code&gt;DateTime&lt;/code&gt;. Instead, use one of the established libraries: &lt;a href="https://momentjs.com/" rel="noopener noreferrer"&gt;Moment.js&lt;/a&gt; or &lt;a href="https://day.js.org/" rel="noopener noreferrer"&gt;Day.js&lt;/a&gt;. And in the near future, use the successor of &lt;code&gt;Date&lt;/code&gt;, the new &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal" rel="noopener noreferrer"&gt;Temporal API&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
