Have you ever wondered why some pieces of JavaScript code seem to run out of order? The key to understanding this is the event loop.
JavaScript's event loop can be tricky to understand, especially when dealing with different types of asynchronous operations. In this article, we'll break down how JavaScript handles synchronous and asynchronous code, microtasks and macrotasks, and why certain things happen in a specific order.
JavaScript handles operations in two main ways: synchronous and asynchronous. Understanding the difference between them is key to grasping how JavaScript handles tasks and how to write efficient and non-blocking code.
Synchronous code is the default in JavaScript, meaning each line runs one after another in sequence. For example:
console.log("First"); console.log("Second");
This will output:
First Second
Asynchronous code on the other hand allows certain tasks to run in the background and complete later, without blocking the rest of the code. Functions like setTimeout() or Promise are examples of asynchronous code.
Here's a simple example of asynchronous code using setTimeout():
console.log("First"); setTimeout(() => { console.log("Second"); }, 0); console.log("Third");
This will output:
First Third Second
There are a few ways to handle asynchronous operations in JavaScript:
Code Sample:
console.log("Start"); function asyncTask(callback) { setTimeout(() => { console.log("Async task completed"); callback(); }, 2000); } asyncTask(() => { console.log("Task finished"); }); console.log("End");
Code Sample:
console.log("Start"); const asyncTask = new Promise((resolve) => { setTimeout(() => { console.log("Async task completed"); resolve(); }, 2000); }); asyncTask.then(() => { console.log("Task finished"); }); console.log("End");
Code Sample:
console.log("Start"); async function asyncTask() { await new Promise((resolve) => { setTimeout(() => { console.log("Async task completed"); resolve(); }, 2000); }); console.log("Task finished"); } asyncTask(); console.log("End");
To better understand each of these method of execution of javascript and how they differs from each either, here is an elaborate differences across multiple aspect of javascript functions.
Aspect | Synchronous Code | Asynchronous Code |
---|---|---|
Execution Order | Executes line by line in a sequential manner | Allows tasks to run in the background while other code continues to execute |
Performance | Can lead to performance issues if long-running tasks are involved | Better performance for I/O-bound operations; prevents UI freezing in browser environments |
Code Complexity | Generally simpler and easier to read | Can be more complex, especially with nested callbacks (callback hell) |
Memory Usage | May use more memory if waiting for long operations | Generally more memory-efficient for long-running tasks |
Scalability | Less scalable for applications with many concurrent operations | More scalable, especially for applications handling multiple simultaneous operations |
This comparison highlights the key differences between synchronous and asynchronous code, helping developers choose the appropriate approach based on their specific use case and performance requirements.
In JavaScript, microtasks and macrotasks are two types of tasks that are queued and executed in different parts of the event loop, which determines how JavaScript handles asynchronous operations.
Microtasks and macrotasks are both queued and executed in the event loop, but they have different priorities and execution contexts. Microtasks are processed continuously until the microtask queue is empty before moving on to the next task in the macrotask queue. Macrotasks, on the other hand, are executed after the microtask queue has been emptied and before the next event loop cycle starts.
Microtasks are tasks that need to be executed after the current operation completes but before the next event loop cycle starts. Microtasks get priority over macrotasks and are processed continuously until the microtask queue is empty before moving on to the next task in the macrotask queue.
console.log("Start"); Promise.resolve().then(() => { console.log("Microtask"); }); console.log("End");
Start End Microtask
Macrotasks are tasks that are executed after the microtask queue has been emptied and before the next event loop cycle starts. These tasks represent operations like I/O or rendering and are usually scheduled after a certain event or after a delay.
console.log("Start"); setTimeout(() => { console.log("Macrotask"); }, 0); console.log("End");
Start End Macrotask
Aspect | Microtasks | Macrotasks |
---|---|---|
Execution Timing | Executed immediately after the current script, before rendering | Executed in the next event loop iteration |
Queue Priority | Higher priority, processed before macrotasks | Lower priority, processed after all microtasks are complete |
Examples | Promises, queueMicrotask(), MutationObserver | setTimeout(), setInterval(), I/O operations, UI rendering |
Use Case | For tasks that need to be executed as soon as possible without yielding to the event loop | For tasks that can be deferred or don't require immediate execution |
이벤트 루프는 JavaScript가 단일 스레드임에도 불구하고 비차단 비동기 작업을 가능하게 하는 JavaScript의 기본 개념입니다. 비동기 콜백을 처리하고 시간이 많이 걸리는 작업으로 인해 차단되지 않고 JavaScript가 계속해서 원활하게 실행되도록 하는 역할을 담당합니다.
이벤트 루프는 JavaScript가 비동기 작업을 효율적으로 처리할 수 있게 해주는 메커니즘입니다. 호출 스택과 작업 큐(또는 마이크로태스크 큐)를 지속적으로 확인하여 다음에 실행해야 할 기능을 결정합니다.
이벤트 루프를 더 잘 이해하려면 JavaScript가 내부적으로 어떻게 작동하는지 아는 것이 중요합니다. JavaScript는 단일 스레드 언어이므로 한 번에 한 가지 작업만 수행할 수 있다는 점을 기억하는 것이 중요합니다. 실행할 함수를 저장하는 호출 스택은 하나만 있습니다. 이는 동기 코드를 간단하게 만들지만, 서버에서 데이터를 가져오거나 시간 제한을 설정하는 등 완료하는 데 시간이 걸리는 작업에 문제를 야기합니다. 이벤트 루프가 없으면 JavaScript는 이러한 작업을 기다리며 멈춰서 아무 일도 일어나지 않을 것입니다.
콜스택은 현재 실행 중인 함수가 보관되는 곳입니다. JavaScript는 코드를 처리하면서 호출 스택에 기능을 추가하고 제거합니다.
setTimeout, fetch 또는 Promise와 같은 비동기 작업이 발생하면 JavaScript는 해당 작업을 백그라운드에서 작업을 처리하는 브라우저의 웹 API(예: Timer API, Network API 등)에 위임합니다.
비동기 작업이 완료되면(예: 타이머가 완료되거나 서버에서 데이터가 수신됨) 콜백(결과를 처리하는 함수)이 작업 큐(또는 약속의 경우 마이크로태스크 큐)로 이동됩니다. .
JavaScript는 동기 코드를 계속 실행합니다. 호출 스택이 비면 이벤트 루프는 작업 대기열(또는 마이크로 작업 대기열)에서 첫 번째 작업을 선택하여 실행을 위해 호출 스택에 배치합니다.
이 과정이 반복됩니다. 이벤트 루프는 현재 동기 작업이 완료된 후 모든 비동기 작업이 처리되도록 보장합니다.
이제 이벤트 루프의 작동 방식을 더 명확하게 이해했으니 이해를 돕기 위해 몇 가지 예를 살펴보겠습니다.
function exampleOne() { console.log("Start"); setTimeout(() => { console.log("Timeout done"); }, 1000); Promise.resolve().then(() => { console.log("Resolved"); }); console.log("End"); } exampleOne();
Start End Resolved Timeout done
function exampleTwo() { console.log("Start"); setTimeout(() => { console.log("Timer 1"); }, 0); Promise.resolve().then(() => { console.log("Promise 1 Resolved"); setTimeout(() => { console.log("Timer 2"); }, 0); return Promise.resolve().then(() => { console.log("Promise 2 Resolved"); }); }); console.log("End"); } exampleTwo();
Start End Promise 1 Resolved Promise 2 Resolved Timer 1 Timer 2
function exampleThree() { console.log("Step 1: Synchronous"); setTimeout(() => { console.log("Step 2: Timeout 1"); }, 0); Promise.resolve().then(() => { console.log("Step 3: Promise 1 Resolved"); Promise.resolve().then(() => { console.log("Step 4: Promise 2 Resolved"); }); setTimeout(() => { console.log("Step 5: Timeout 2"); }, 0); }); setTimeout(() => { console.log( "Step 6: Immediate (using setTimeout with 0 delay as fallback)" ); }, 0); console.log("Step 7: Synchronous End"); } exampleThree();
Step 1: Synchronous Step 7: Synchronous End Step 3: Promise 1 Resolved Step 4: Promise 2 Resolved Step 2: Timeout 1 Step 6: Immediate (using setTimeout with 0 delay as fallback) Step 5: Timeout 2
In JavaScript, mastering synchronous and asynchronous operations, as well as understanding the event loop and how it handles tasks, is crucial for writing efficient and performant applications.
The examples provided progressively illustrated the interaction between synchronous code, promises, timers, and the event loop. Understanding these concepts is key to mastering asynchronous programming in JavaScript, ensuring your code runs efficiently and avoids common pitfalls such as race conditions or unexpected execution orders.
To ensure you don't miss any part of this series and to connect with me for more in-depth discussions on Software Development (Web, Server, Mobile or Scraping / Automation), push notifications, and other exciting tech topics, follow me on:
Stay tuned and happy coding ???
위 내용은 JavaScript의 비동기 프로그래밍 이해: 이벤트 루프 초보자 가이드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!