{"componentChunkName":"component---src-templates-blog-jsx","path":"/blog/finally-understanding-node-internals","result":{"data":{"mdx":{"frontmatter":{"title":"Finally understanding Node.js internals.","date":"2021-04-30","subtitle":"A straightforward post about some of the Node.js internals aspects, like V8, Event Loop, JIT, Libuv, and more bonus topics.","coverCredit":"@tomadamsmia","coverWebsite":"Unsplash","cover":{"publicURL":"/static/dfd11f185e3743176eac35dc6a8ab588/cover.jpg","childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEEA//EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAYFmiokD/8QAGhAAAgMBAQAAAAAAAAAAAAAAAQIAEiEDMf/aAAgBAQABBQJNjGq82QI2Cxp7P//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EAB0QAAICAQUAAAAAAAAAAAAAAAARASEQIjFRYZH/2gAIAQEABj8Crcp2ak+x8yiPMf/EABoQAQADAQEBAAAAAAAAAAAAAAEAESExQVH/2gAIAQEAAT8htjLVBfIiAsNfkI2T1pssl1U38nqYGJdDnK5P/9oADAMBAAIAAwAAABAgz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB0QAQEAAgIDAQAAAAAAAAAAAAERACExQWGRofD/2gAIAQEAAT8QTEJyRwS+NP5yXMIDA+e+zN88IT9Y3rdmwCJPeNhLwzkHV95a00hdoZ//2Q==","aspectRatio":1.5,"src":"/static/dfd11f185e3743176eac35dc6a8ab588/cf77e/cover.jpg","srcSet":"/static/dfd11f185e3743176eac35dc6a8ab588/8196e/cover.jpg 258w,\n/static/dfd11f185e3743176eac35dc6a8ab588/26313/cover.jpg 516w,\n/static/dfd11f185e3743176eac35dc6a8ab588/cf77e/cover.jpg 1032w,\n/static/dfd11f185e3743176eac35dc6a8ab588/7022b/cover.jpg 1548w,\n/static/dfd11f185e3743176eac35dc6a8ab588/14c55/cover.jpg 2064w,\n/static/dfd11f185e3743176eac35dc6a8ab588/9eda0/cover.jpg 4896w","sizes":"(max-width: 1032px) 100vw, 1032px"}}}},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Finally understanding Node.js internals.\",\n  \"author\": \"Patrick Passarella\",\n  \"date\": \"2021-04-30\",\n  \"subtitle\": \"A straightforward post about some of the Node.js internals aspects, like V8, Event Loop, JIT, Libuv, and more bonus topics.\",\n  \"cover\": \"./cover.jpg\",\n  \"coverCredit\": \"@tomadamsmia\",\n  \"coverWebsite\": \"Unsplash\",\n  \"published\": true\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"h1\", null, \"Scope\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"First of all, what does \", mdx(\"em\", {\n    parentName: \"strong\"\n  }, \"node internals\"), \" means?\"), \"\\nNode internals is the structure of Node, how does it work, why it works like that, what technologies are involved, things like that.\"), mdx(\"p\", null, \"In this post, I will talk about some of the core technologies Node is composed, a more top-down perspective on how they work, and some additional info that may help you understand some more about it.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"More specifically:\")), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"V8 Engine\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"JIT Paradigm\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Non-blocking I/O\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Libuv\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Event Loop\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Generators\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Async Await\")), mdx(\"p\", null, \"This is not an advanced post, actually, it's the other way around, a post for you to finally understand the basics of how Node works, because there's too much about it.\"), mdx(\"h1\", null, \"Why\"), mdx(\"p\", null, \"Why learn node internals?\\nFirst, knowledge is always welcomed, especially if it will make a big change in your technical thinking skills, and this is the case. Second, understanding how things work, will make you develop better, and find and fix bugs easier.\"), mdx(\"h1\", null, \"V8 Engine\"), mdx(\"p\", null, \"We need to start talking about V8, because almost everything is related to it.\"), mdx(\"p\", null, \"V8 is an engine created by Google, written in C++, that compiles JavaScript source code to native machine code at runtime. It was created to optimize javascript execution inside browsers.\"), mdx(\"p\", null, \"Javascript is an \\\"interpreted\\\" language, but the v8 \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"compiles\"), \" the code and optimizes the execution, allowing the execution to be done on top of the compiled code.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Javascript execution in V8 is divided into three stages:\")), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Source to syntax tree:\"), \" The parser generates an abstract syntax tree (AST) from the source code;\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Syntax tree to bytecode:\"), \" V8 \", mdx(\"em\", {\n    parentName: \"li\"\n  }, \"Ignition\"), \" generates bytecode from the syntax tree;\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Bytecode to machine code:\"), \" V8 \", mdx(\"em\", {\n    parentName: \"li\"\n  }, \"TurboFan\"), \" generates a graph from bytecode, replacing sections of bytecode with machine code.\")), mdx(\"p\", null, \"These two last stages operate within the just-in-time (JIT) paradigm.\"), mdx(\"h1\", null, \"JIT paradigm\"), mdx(\"p\", null, \"To execute any program, the computer must translate the code to machine language. There are a few ways to do that.\"), mdx(\"h3\", null, \"Interpreter:\"), mdx(\"p\", null, \"Translates and then executes, line by line. Has fast translation (easy) and slow execution;\"), mdx(\"h3\", null, \"Compiler:\"), mdx(\"p\", null, \"Compile all the code to machine code at once before executing it. Slow translation (complex), but fast execution.\"), mdx(\"h3\", null, \"JIT (Just in Time) compilation:\"), mdx(\"p\", null, \"Compilation at run time. Combine the best parts from both interpreter and compiler, making translation and execution fast.\\nThe code is run through an interpreter (Ignition), and during execution, it keeps track of code segments that can be reused where possible, and others that can be used to make optimizations based on assumptions (TurboFan).\"), mdx(\"p\", null, \"The main problem the interpreter have is that if you pass the same line of code 10 times, it will translate 10 times. JIT tries to avoid retranslations.\"), mdx(\"p\", null, \"The JIT compiler can expose overhead memory consumption. \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Ignition\"), \" addresses this by achieving three objectives: reducing memory usage, reducing startup time, and reducing complexity. All three objectives are accomplished by compiling AST to bytecode and collecting feedback during program execution.\"), mdx(\"h1\", null, \"Threads\"), mdx(\"p\", null, \"Some info about threads, which is commonly confused by people.\"), mdx(\"p\", null, \"A thread is something that is associated with an instance of each program we run, it's an operation that our CPU needs to perform.\"), mdx(\"p\", null, \"There are two types of threads.\"), mdx(\"h3\", null, \"Single Thread\"), mdx(\"p\", null, \"Only one piece of code can be executed at a time.\\nFor instance, if multiple requests are sent to a server, the next one needs to wait for the current one to send back a response to be processed.\"), mdx(\"h3\", null, \"Multi Thread\"), mdx(\"p\", null, \"Multiple pieces of code can be executed at the same time, in parallel.\\nEach request sent to a server simultaneously will create a new thread to process it.\"), mdx(\"p\", null, \"Javascript/Node being single-threaded does not mean it needs to wait for a request to be done, and also doesn't mean that it doesn't use threads internally.\"), mdx(\"h1\", null, \"Non-blocking I/O\"), mdx(\"p\", null, \"Since JavaScript execution in Node.js is single-threaded, it is possible to start an I/O process, but not block non-dependent tasks, it means that it can just start the communication, and continue to process other tasks that don\\u2019t need the I/O response, if a task needs the response, it will wait for it and then execute a callback. It helps parallel execution and the use of resources.\"), mdx(\"h2\", null, \"How is it done?\"), mdx(\"p\", null, \"Instead of waiting for the process to complete, it sends it to a \\u201Cworker\\u201D, and frees the thread, while it is processing the data, the thread can process another task.\"), mdx(\"h2\", null, \"Examples\"), mdx(\"h3\", null, \"Blocking\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const content = fs.readFileSync('path'); // 1\\n\\nconsole.log(content); // 2\\nconsole.log('Executed'); // 3\\n\\n// The file content\\n// Executed\\n\")), mdx(\"p\", null, \"The last \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"console.log\"), \" is totally independent of the file read operation, it doesn't need its result, but even then, it needs to wait for it to complete before executing.\"), mdx(\"h3\", null, \"Non-blocking\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"fs.readFile('path', (content) => {\\n  console.log(content);\\n});\\n\\nconsole.log('Executed');\\n\\n// Executed\\n// The file content\\n\")), mdx(\"p\", null, \"In this case, the last \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"console.log\"), \" is executed first, which is great, because again, it doesn't need the file read result, so it doesn't make sense to wait for it.\\nThis is done because Node throws the process to the \\\"worker\\\", and while it is doing its work, Node goes to execute the second task, which is the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"console.log('Executed')\"), \".\"), mdx(\"h1\", null, \"Libuv\"), mdx(\"p\", null, \"Libuv is an open-source library written in C, that uses a thread-pool (multi-thread) to manage parallel operations.\"), mdx(\"p\", null, \"So, what are those \", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"workers\"), \" I have been talking about? Well, they are part of Libuv.\\nWorkers are non-blocking async I/O processes in the background managed by Libuv. Each sync I/O operation they receive from the event loop is run on a background thread, to not block the main thread.\"), mdx(\"p\", null, \"Libuv also provides the \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"event loop\"), \", where it was made to be tied with only a single thread. You can run multiple event loops, but it must be one per thread.\\nInside Libuv, there are a lot of concepts, like handles, who are abstractions to some resources like TCP/UDP and signals. There are also handles to interact with the event loop, like \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"idle\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"prepare\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"check\"), \", and some async types. Each one serves to do a specific action with the event loop, such as run something before or after Libuv does I/O polling for example.\"), mdx(\"p\", null, \"Also, some modules from Node comes from Libuv, like the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"fs\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"child_process\"), \" module.\"), mdx(\"h3\", null, \"Async File I/O\"), mdx(\"p\", null, \"When a task for something like a file I/O is put in the call stack, the event loop sends it to the Libuv thread pool, when the data is processed, it puts it in the \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Task Queue\"), \", for the event loop to call when it is available.\"), mdx(\"h3\", null, \"Network I/O\"), mdx(\"p\", null, \"The thread pool is bypassed completely when executing low-level OS operations, like a REST API call. Libuv nor node handle these. Instead, there\\u2019s something called OS Async Helpers, where the operations are executed immediately as soon as a CPU is available.\"), mdx(\"p\", null, \"After the task is done, it puts the callback into the \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Job Queue\"), \", for the event loop to call after the call stack is empty.\"), mdx(\"p\", null, \"All network I/O are performed on sockets which are polled using epoll/kqueue/IOCP (system event interfaces).\"), mdx(\"h1\", null, \"Event Loop\"), mdx(\"p\", null, \"We can think about the event loop like someone who sends tasks to the right places, for example, if it gets a task, it will get it from the call stack, see if it can be run on the system primitive (kqueue, epoll), if yes, it will send to it and them get back the response after it\\u2019s done, if not, it will send to a background worker. So it\\u2019s literally just \\u201Ccommunication\\u201D.\"), mdx(\"p\", null, \"But in the middle of all that communication, it also manages a lot of other stuff, like timers, and other callbacks.\"), mdx(\"p\", null, \"The event loop is what allows Node.js to perform non-blocking I/O operations, by offloading operations to the system kernel whenever possible. The event loop will go through a phase, execute the callbacks related to that phase, and then move to the next one. Each phase has a callback queue. Depending on the task, it will send it to the corresponding queue.\"), mdx(\"p\", null, \"When Node.js starts, it initializes the event loop, processes the script, then begins processing the event loop.\\nThe loop only stops when there are no more tasks queued in the event loop or in the call stack.\"), mdx(\"h2\", null, \"Phases\"), mdx(\"p\", null, mdx(\"span\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"308px\"\n    }\n  }), \"\\n      \", mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"183.72093023255815%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAlCAYAAABCr8kFAAAACXBIWXMAAAsSAAALEgHS3X78AAAC5UlEQVRIx5WWV24qQRBFWQQmJ2OTM8aYDAKEiB/sfzH1dEq6aGRZj+ajGLqm+/atPLF0Om2dTsdms5n9/PzYeDy2r68v+/7+tslk8pBSqWSZTMZyudx/JcamVqtlzWbTKpWKDQYDWywWNhqNrF6vW7VatW63a+/v768BIhzu9Xq22+1suVw6YK1Wc10wICYDBiPY9ft9dwGshsOh63gXbHI2m7VCoeDmIh8fHw7aaDT8v3RsZu9TQH64OZlMWiqVsre3NwdBn0gkHnqBPQN1hjDARARziXDUdFwSzFA+5CCR/kvwY3BQ2Ljf7221WtnxeLTL5WLb7daf5/PZIw5gcFDK5bIfwDzSg6TGXHREGR3rYIbFYtFzjUPyoYDkQ/6TCUE+hGE+n3fhEEp8Kr10wVHmIIfwEWbBGGakTlQXDMhmRVImR82XD6OgT6PMYSqDwyo/Pannl2oZs2DCwfl8bofDwRvD9Xr1/1z0UreRz2CjrhMVRf2lPKT0BIA/6S6qHHSwDy49TGGjGkE8HrfPz0/X0SjQIawRShWBbVSkd0BYwkIdmoDAjISXjpyEAemEjicXYx1PnfegqJniR/kSnSLNO9gBijt4z5xZr9ePPkDwmEkelHa77f6CES9oCBxkDRNmDJthwBBjoNE87ve7CxlBQ3FApQ23AoZwO+w0U+iPXIhruIiD6GB3Op3cCi7lnAPCkA1spttIWEuH/2SyXAEwQKxJfgckKHI4TyIGSy76nSZaq5lIF13HiNJfgEqn6EE9o/Jb5yarH6opYKLMkA7goMRW6akieCrqCLqXOjYbAVAiE5zb7eapI0CYBteyGIqValqX4M+Xp56+aRD8BUs1XM2WYB/qM0MFTyPgAsYCXwwq+uARoJkRnR+Y+9dMCWKoSqEClDrRlOE/LgieKdSnvmOm06mXEyXEGGAtXwYHBWfrg4iZAhDdhMLfbDae5LwLBsTxsKO3wQgwBJasuYQGEGryPzDFIOgSS9nNAAAAAElFTkSuQmCC')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  })), \"\\n  \", mdx(\"img\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"Event Loop\",\n    \"title\": \"Event loop\",\n    \"src\": \"/static/917f40400cc849d71c917705d15cfea7/2ece4/event_loop_stages.png\",\n    \"srcSet\": [\"/static/917f40400cc849d71c917705d15cfea7/d9489/event_loop_stages.png 258w\", \"/static/917f40400cc849d71c917705d15cfea7/2ece4/event_loop_stages.png 308w\"],\n    \"sizes\": \"(max-width: 308px) 100vw, 308px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  })), \"\\n    \")), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"timers:\"), \" Executes callbacks scheduled by setTimeout() and setInterval().\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"pending callbacks:\"), \" Executes callbacks for some system operations.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"idle, prepare:\"), \" Libuv handles, idle will run the given callbacks once per loop iteration, prepare runs before libuv does its I/O polling.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"poll:\"), \" Retrieve new I/O events and execute I/O related callbacks;\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"check:\"), \" Execute setImmediate() callbacks.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"close callbacks:\"), \" Execute close callbacks, e.g. socket.on('close', ...).\"), mdx(\"h2\", null, \"Final diagram\"), mdx(\"p\", null, mdx(\"span\", _extends({\n    parentName: \"p\"\n  }, {\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"811px\"\n    }\n  }), \"\\n      \", mdx(\"span\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"61.627906976744185%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsSAAALEgHS3X78AAABeElEQVQoz22T666CQAyEeQwUVC4KXhAFAeOFYEIC7/9EPfmalKPRH83S0k6n012nLEs5Ho+S57ksl0vZ7XZSFIWcTifZbrfieZ7MZjMJw1CappHz+SzUrNdrzQ+CQHzf1zxOp65rud1umpQkiaRpKvv9XsHwF4uFFhF/PB7Stq3mbjYbbYIBPAHSEYYYSQBRAEN8Y4GRczgcdIrVaqUWRdEnIInQpxMJADI+xcRhSJwCy+VEBosBhO+6rjjz+XwKUox+z+dTZciybGJIMcDGOo7jSXtYIwlTOdaFJLqQMAyD9H2v4ADYOGjKf8ZEZ5bEDq7Xq+Z2XfcPCDu+ORmfbiQBgGYAMhKNmQqDgH2bfQESpAhQ2Jm+thhYctpSaPRuH4CAUWxbBgzQcRzl9XpJVVVyv9/1H/qZxibJT0BAKGRc2FBwuVz0QqMbhgQYN8Im+wLEARDfLjZxGLIkBAeY7cPQrtZPhnYH318FQObbiMTtAZi+788O+wOxCFcnhJI5JQAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  })), \"\\n  \", mdx(\"img\", _extends({\n    parentName: \"span\"\n  }, {\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"Event Loop Complete\",\n    \"title\": \"Event loop complete diagram\",\n    \"src\": \"/static/348dfe38972583236eddee6b30f3a6d5/fd28b/event_loop_complete.png\",\n    \"srcSet\": [\"/static/348dfe38972583236eddee6b30f3a6d5/d9489/event_loop_complete.png 258w\", \"/static/348dfe38972583236eddee6b30f3a6d5/75dcb/event_loop_complete.png 516w\", \"/static/348dfe38972583236eddee6b30f3a6d5/fd28b/event_loop_complete.png 811w\"],\n    \"sizes\": \"(max-width: 811px) 100vw, 811px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\"\n  })), \"\\n    \")), mdx(\"h3\", null, \"Quick recap\"), mdx(\"p\", null, \"Looking in that diagram, I will follow the readFile task.\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"A read file task is placed on the call stack.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"The event loop sends it to Libuv background threads.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"While the threads are working, the event-loop single-thread can process another task since it's empty.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"After the Libuv threads are done processing the readFile callback, it sends it to the respective queue, in this case, the Task Queue.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"After the call stack is empty, the event-loop grabs the readFile callback from the Task Queue and place it on the call stack to be executed.\")), mdx(\"p\", null, \"Now, the API request example.\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"An API request task is placed on the call stack.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"The event loop sends it to the OS to process.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"While the OS is working, the event-loop single-thread can process another task since it's empty.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"After the OS is done processing, it sends it to the respective queue, in this case, the Job Queue.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"After the call stack is empty, the event-loop grabs the API request callback from the Job Queue and place it on the call stack to be executed.\")), mdx(\"h1\", null, \"Generators\"), mdx(\"p\", null, \"This is more like extra content, but generators also have a pretty good part inside Node.\\nBut first, let's see about Iterators.\"), mdx(\"h2\", null, \"Iterators\"), mdx(\"p\", null, \"An iterator is an object that produces a sequence of values and return a value on its end.\"), mdx(\"h3\", null, \"What is defined as an iterator\"), mdx(\"p\", null, \"An object to be defined as an iterator needs to implement a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"next\"), \" method, which needs to return an object containing two properties:\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Done:\"), \" Defines if the sequence is finished or not\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Value:\"), \" Any value returned by the iterator\"), mdx(\"p\", null, \"An iterator object can be iterated by calling the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"next\"), \" method. When all the values are iterated, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"done\"), \" property returns true.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const iterator = [1, 2, 3][Symbol.iterator]();\\niterator.next(); // { value: 1, done: false }\\niterator.next(); // { value: 2, done: false }\\n// ...\\niterator.next(); // { value: undefined, done: true }\\n\")), mdx(\"h2\", null, \"Creating an Iterator\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"function makeRangeIterator(start = 0, end = Infinity) {\\n  let nextIndex = start;\\n  let iterationCount = 0;\\n\\n  const rangeIterator = {\\n    next: function () {\\n      let result;\\n      if (nextIndex < end) {\\n        result = { value: nextIndex, done: false };\\n        nextIndex++;\\n        iterationCount++;\\n        return result;\\n      }\\n      return { value: iterationCount, done: false };\\n    },\\n  };\\n  return rangeIterator;\\n}\\n\")), mdx(\"p\", null, \"That'll seem like too much code, but it's pretty straightforward.\\nThe function implements and returns the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"next\"), \" function, in which when you call it, it will increment the current index, and return the result, which it's the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"value\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"done\"), \" object. When it's the final index, we just return the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"done: true\"), \". In this example, I used just the iteration count for the value.\"), mdx(\"p\", null, \"This implementation is considered an Iterator since it has all the requirements.\"), mdx(\"h2\", null, \"Now back to generators\"), mdx(\"p\", null, \"Generators are a type of function that can be executed, paused, and resumed in a controlled manner.\\nThere are two main things that generators are used for, implementing lazy iterators and blocking asynchronous calls.\"), mdx(\"p\", null, \"Here is the same function above, but implemented using generators.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"function* makeRangeIterator(start = 0, end = Infinity) {\\n  let iterationCount = 0;\\n\\n  for (let i = start; i < end; i++) {\\n    iterationCount++;\\n    yield i;\\n  }\\n\\n  return iterationCount;\\n}\\n\")), mdx(\"p\", null, \"Very noticeable better. Generators have that special syntax that you need to add an \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"*\"), \" after the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"function\"), \" keyword, this determines that this function is a generator.\\nBesides that, the only other weird thing is the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"yield\"), \" keyword. When the code is being executed, it will stop right when it reaches the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"yield\"), \", and the value after the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"yield\"), \", in this case, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"i\"), \", is the value that will be returned in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"value\"), \" property from that iteration.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const generator = makeRangeIterator();\\ngenerator.next(); // { value: 0, done: false }\\ngenerator.next(); // { value: 1, done: false }\\ngenerator.next(); // { value: 2, done: false }\\n// ...\\n\")), mdx(\"p\", null, \"You can also inject a value by passing the value to the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"next\"), \" function, like so, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"generator.next('new value')\"), \".\"), mdx(\"h1\", null, \"Async Await\"), mdx(\"p\", null, \"Have you ever wondered how this thing works? Me neither, but I will show you.\"), mdx(\"p\", null, \"Async Await is a way to pause the execution of a code on the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"await\"), \" keyword, when used on a promise, and resume only when the promise is resolved.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"So we need 3 things to make something like this work.\")), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Pause a function\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Put a value inside the function\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Resume a function\")), mdx(\"p\", null, \"And that's exactly what generators allowed us to do!\"), mdx(\"p\", null, \"So, let's implement our own Async Await, why not.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const wrapToReturnPromise = function (gen) {\\n  const generator = gen();\\n  const { value } = generator.next();\\n\\n  if (value.isPromise()) { // pseudo-code\\n    return value\\n      .then((val) => generator.next(val))\\n      .catch((err) => generator.throw(err));\\n  }\\n\\n  // Error if not promise\\n};\\n\")), mdx(\"p\", null, \"Here we created a function that receives a generator function from its parameters, then we call the generator \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"next\"), \" method to get its initial value, after that, we check if that value is a promise and we call \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"next\"), \" again inside the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"then\"), \", but this time injecting the value to it (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"generator.next(val)\"), \"), which would cause it to be returned as \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"{value: val, done}\"), \" object.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const fakeApi = function () {\\n  return new Promise((resolve, reject) => {\\n    setTimeout(() => {\\n      return resolve('Fake data');\\n    }, 1000);\\n  });\\n};\\n\\nconst foo = wrapToReturnPromise(function* () {\\n  try {\\n    const val = yield fakeApi();\\n    console.log(val); // \\\"Fake data\\\"\\n    return val;\\n  } catch (err) {\\n    console.log('Error: ', err.message);\\n  }\\n});\\n\")), mdx(\"p\", null, \"Here is the interesting part, we call the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"wrapToReturnPromise\"), \", passing in our generator function, which in this case just calls a function that returns a Promise and logs it, but we can see that it behaves exactly like an async await function, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"yield\"), \" will tell the runtime to stop there, just like the await, and after the promise is resolved, it resumes and logs the returned value!. Very cool (for me at least).\"), mdx(\"p\", null, \"And here's where I'm gonna end this post, I hope it was useful for you and you learned something. This stuff may be difficult to understand sometimes, but time will take care of it.\"));\n}\n;\nMDXContent.isMDXComponent = true;","excerpt":"Scope First of all, what does  node internals  means? \nNode internals is the structure of Node, how does it work, why it works like that…","fields":{"slug":"finally-understanding-node-internals"}}},"pageContext":{"slug":"finally-understanding-node-internals","previous":{"fields":{"slug":"making-decisions-with-decision-matrix"}},"next":null}},"staticQueryHashes":["2337317332","3351591964"]}