찾다
웹 프론트엔드JS 튜토리얼nodejs의 이벤트 루프 메커니즘에 대한 자세한 설명

이 글은 node의 이벤트 루프 메커니즘을 이해하는 데 도움이 됩니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.

nodejs의 이벤트 루프 메커니즘에 대한 자세한 설명

프런트엔드 개발은 JavaScript와 분리될 수 없습니다. JavaScript는 웹 개발에 주로 사용되며 브라우저에서 구문 분석되고 실행되는 웹 프론트엔드 언어입니다. js의 역할은 프론트엔드 개발에만 국한되지 않고, 서버사이드 개발인 nodejs에도 사용될 수 있습니다. 이상과 야망을 가진 프런트엔드 사람으로서 시야를 넓히고 서버 측 개발 언어를 마스터하고 싶다면 nodejs가 매우 좋은 선택입니다.

관련 권장 사항: "nodejs Tutorial"

js 개발 방법을 마스터했으므로 노드를 시작하기 쉽고 npm 패키지 관리 도구도 개발 경험을 크게 향상시킵니다. Nodejs는 비동기 비차단 I/O 작업 방식으로 유명하며, 해당 처리 메커니즘을 이벤트 루프라고 합니다.

노드 이벤트 루프 메커니즘을 이해하면 노드의 이벤트 처리 방법과 비동기 이벤트의 실행 타이밍을 더 잘 이해할 수 있습니다. 이 기사에서는 주로 nodejs의 이벤트 루프 메커니즘을 설명하고 노드 후속 학습의 기초를 마련합니다.

1. node VS javascript

앞서 언급한 것처럼 Javascript는 주로 웹 개발에 사용되는 웹 프런트엔드 언어로, 브라우저에서 구문 분석하고 실행하는 반면 node.js는 이를 기반으로 하는 JavaScript 실행 환경입니다. Chrome V8 엔진입니다. 따라서 nodejs는 언어, 라이브러리, 프레임워크가 아니라 js 런타임 환경입니다. 간단히 말해서 node는 js 코드를 구문 분석하고 실행할 수 있습니다. 과거에는 브라우저에서만 JS를 구문 분석하고 실행할 수 있었지만 이제는 브라우저 없이도 노드를 사용하여 JS를 완전히 실행할 수 있습니다.

node.js와 브라우저 js에는 많은 차이점이 있습니다. 예를 들어 브라우저의 js에는 ecmascript, BOM, DOM이 포함되어 있지만 nodejs의 js에는 BOM과 DOM이 없고 emcscript만 있습니다. 그리고 노드의 js 실행 환경은 파일 읽기 및 쓰기, 네트워크 서비스 구축, 네트워크 통신, http 서버 등과 같은 js용 서버 수준 작업 API를 제공합니다. 이러한 API의 대부분은 핵심 모듈에 패키지되어 있습니다. 또한 노드의 이벤트 루프 메커니즘은 브라우저 js의 이벤트 루프 메커니즘과 다릅니다.

2. JavaScript 이벤트 루프

모두가 이미 브라우저의 js 이벤트 루프에 대해 매우 명확하게 알고 있습니다. 비교를 위해 여기서 간단히 언급하겠습니다.

nodejs의 이벤트 루프 메커니즘에 대한 자세한 설명

(필립 로버츠의 연설 "도와주세요, 이벤트 루프에 갇혀 있어요"에서 인용)

js가 실행되면 동기 작업과 비동기 작업은 각각 다른 실행 환경에 들어갑니다. 동기 작업은 메인 스레드, 즉 메인 실행 스택과 비동기 작업(ajax 요청, settimeout, setinterval, poromise.resolve() 등)에 들어갑니다. ) 작업 대기열을 입력합니다. 다양한 비동기 작업은 ajax 요청, settimeout, setinterval 등과 같은 다양한 작업 대기열로 푸시됩니다. 이러한 작업은 매크로 작업 대기열(매크로 작업)로 푸시되고 Promise 함수는 마이크로 작업 대기열( 마이크로 태스크). 전체적인 이벤트 루프 프로세스는 다음과 같습니다.

  • 동기 코드가 실행되면 기본 실행 스택이 비워지고 준비 작업이 비동기 작업을 실행하기 시작합니다.

  • 메인 스레드는 마이크로태스크 대기열이 비어 있는지 확인합니다. 비어 있지 않으면 대기열의 모든 마이크로태스크를 순회하여 실행하고 마이크로태스크 대기열을 지운 다음 매크로태스크 대기열을 확인합니다. 마이크로태스크 대기열이 비어 있으면 다음 단계로 바로 진행하세요.

  • 메인 스레드는 매크로 작업 대기열을 순회하여 매크로 작업 대기열의 첫 번째 매크로 작업을 실행합니다. 실행 중에 매크로 작업이나 마이크로 작업을 발견하면 계속해서 해당 작업 대기열로 푸시합니다. 매크로 작업이 실행되면 마이크로 작업 대기열을 순회하고 비워야 합니다

  • 렌더링 작업을 수행하고 뷰를 업데이트합니다

  • 다음 이벤트 루프를 시작하고 두 작업 대기열이 지워질 때까지 위 단계를 반복합니다

영향을 더욱 심화시키기 위해 작은 예를 들어 다음 코드가 무엇을 출력하는지 살펴보겠습니다.

    var le=Promise.resolve(2);
    console.log(le)
    console.log('3')
    Promise.resolve().then(()=>{
    console.log('Promise1')  
    setTimeout(()=>{
        console.log('setTimeout2')
    },0)
    })
    setTimeout(()=>{
    console.log('setTimeout1')
    Promise.resolve().then(()=>{
        console.log('Promise2')    
    })
    },0);

위의 이벤트 루프 프로세스를 사용하여 분석합니다.

  • js 기본 프로세스 실행 코드에서 Promise.resolve(2 ) , 즉시 실행되어 2를 promise 개체로 바꾼 다음 console.log(le)가 le 변수를 인쇄합니다. ----->Promise {:
  • console .log( '3'), print ----->3
  • 그런 다음 실행을 계속하다가 마이크로태스크 스택으로 푸시된 비동기 마이크로태스크 함수인 Promise.resolve()를 만나게 됩니다
  • 다음 함수는 다음과 같습니다. setTimeout, 매크로 작업 대기열에 푸시하면 이제 메인 프로세스가 비어 있습니다
  • 마이크로 작업 대기열을 확인하고 Promise.resolve().를 찾은 다음 ----->promise1을 인쇄하고 다른 타이머를 만나 푸시합니다. 작업 대기열 끝에서 마이크로 작업 대기열은 비어 있습니다
  • 매크로 작업 대기열을 확인하고 실행할 첫 번째 매크로 작업을 가져오고 ----->setTimeout1을 인쇄하고 Promise.resolve()를 만나고 다시 푸시합니다. to microtask 대기열
  • 은 다음 매크로 작업을 시작하기 전에 확실히 마이크로 작업을 지울 것입니다. 따라서 setTimeout1을 인쇄한 후 마이크로 작업 대기열이 확인되므로 --->promise2
  • 이벤트 루프의 다음 라운드가 매크로 작업 대기열을 차지합니다. 현재 첫 번째 작업이 실행되었으므로 print------>setTimeout2가 인쇄됩니다. 이 시점에서 매크로 작업과 마이크로 작업 대기열이 모두 지워지고 이벤트 루프가 종료됩니다.

그래서 출력 결과는 다음과 같습니다. : 약속 {: 2 }, 3, promise1, setTimeout1, promise2, setTimeout2.

브라우저에서의 실행 결과는 다음과 같습니다.

nodejs의 이벤트 루프 메커니즘에 대한 자세한 설명

3. 노드 이벤트 루프

노드의 이벤트 루프는 6단계로 이루어지며, 이 6단계는 다음 노드까지 순차적으로 실행됩니다. 이벤트 처리가 완료되었습니다. 6단계의 시퀀스 다이어그램은 다음과 같습니다.

nodejs의 이벤트 루프 메커니즘에 대한 자세한 설명

六个阶段分别是:

  • timers 阶段:这个阶段执行timer(setTimeout、setInterval)的回调
  • I/O callbacks 阶段:执行一些系统操作的回调(比如网络通信的错误回调);
  • idle, prepare 阶段:仅node内部使用,可忽略
  • poll 阶段:获取新的I/O事件, 适当的条件下node将阻塞在这里
  • check 阶段:执行 setImmediate() 的回调
  • close callbacks 阶段:执行 socket 的 close 事件回调,如果一个socket或handle被突然关掉(比如socket.destroy()),close事件将在这个阶段被触发

事件循环中,每当进入某一个阶段,都会从该阶段对应的回调队列中取出函数去执行。当队列为空或者执行的回调函数数量到达系统设定的阈值,该阶段就会终止,然后检查NextTick队列和微任务队列,将其清空,之后进入下一个阶段。

这里面比较关键的是poll阶段:

  • poll队列不为空的时候,事件循环会遍历队列并同步执行回调,直到队列清空或执行回调数达到系统上限。
  • poll队列为空的时候,就会有两种情况:
    • 如果代码中存在setImmediate()回调,那么事件循环直接结束poll阶段进入check阶段来执行check队列里的回调;
    • 如果不存在setImmediate()回调,会等待回调被加入到队列中并立即执行回调,这里同样会有个超时时间设置防止一直等待下去,如果规定时间内有定时器函数进入队列,则返回到timer阶段,执行定时器回调,否则在poll阶段等待回调进入队列。

同样的举个大大的,看看以下代码会输出什么:

console.log('start')
setTimeout(() => {
  console.log('timer1')
  Promise.resolve().then(function() {
    console.log('promise1')
  })
}, 0)
setTimeout(() => {
  console.log('timer2')
  Promise.resolve().then(function() {
    console.log('promise2')
  })
}, 0)
Promise.resolve().then(function() {
  console.log('promise3')
})
console.log('end')

利用node事件循环分析呗:

  • 先执行同步任务,打印start,end
  • 进入timer阶段前,清空NextTick和micro队列,所以打印promise3
  • 进入timer阶段,打印timer1,并发现有一个微任务,立即执行微任务,打印promise1
  • 仍然在timer阶段,执行下个宏任务,打印timer2,同样遇到微任务,立即执行,打印promise2

因此输出顺序是:start,end,promise3,timer1,promise1,timer2,promise2,如果能正确回答出来说明对node的循环机制有了大体的了解,实际node输出结果确实是这样:

nodejs의 이벤트 루프 메커니즘에 대한 자세한 설명

那如下代码会输出什么呢?

process.nextTick(function(){
    console.log(7);
});

new Promise(function(resolve){
    console.log(3);
    resolve();
    console.log(4);
}).then(function(){
    console.log(5);
});

process.nextTick(function(){
    console.log(8);
});

继续分析:

  • process.nextTick会将任务推进至nextTick队列,promise.then会把任务推至micro队列,上面提到过每次一个宏任务执行完,执行下一个宏任务之前需要清空nextTick队列和micro队列,同样的一个阶段执行完,进入下一个阶段之前也需要nextTick队列和micro队列,并且nextTick队列优先级高于micro队列
  • 先执行同步代码,打印3,4
  • 执行nextTick队列,打印7,8
  • 再执行micro队列,打印5

因此最终输出是:3,4,7,8,5,需要记住,process.nextTick 永远大于 promise.then的优先级

还有一个大家很容易混淆的点就是setTimout和setImmediate的执行时机,根据上面描述的node事件循环机制,setImmediate()应该在check阶段执行 与 而setTimeout在timer阶段执行,理论上setTimout比setImmediate先执行,看下面的代码:

setTimeout(() => console.log(1),0);
setImmediate(() => console.log(2));

执行结果是什么?1,2 还是 2,1,其实都有可能,看实际node运行的结果:

nodejs의 이벤트 루프 메커니즘에 대한 자세한 설명

可以看到两次执行的结果不一样,为什么呢?原因在于即使setTimeout的第二个参数默认为0,但实际上,Node做不到0秒就执行其回调,最少也要4毫秒。那么进入事件循环后,如果没到4毫秒,那么timers阶段就会被跳过,从而进入check阶段执行setImmediate回调,此时输出结果是:2,1;

如果进入事件循环后,超过4毫秒(只是个大概,具体值并不确定),setTimeout的回调会出现在timer阶段的队列里,回调将被执行,之后再进入poll阶段和check阶段,此时输出结果是:1,2

那如果两者在I/O周期内调用,谁先执行呢?看一下代码:

const fs = require('fs')

fs.readFile('./test.txt', 'utf8' , (err, data) => {
  if (err) {
    console.error(err)
    return
  }
  setTimeout(() => {
    console.log('timeout');
  }, 0);
  setImmediate(() => {
    console.log('immediate');
  });
})

实际上,node中输出的结果总是immediate先输出,timeout后输出。因为I/O回调是在poll阶段执行,当回调执行完毕之后队列为空,发现存在setImmediate的回调就会进入check阶段,执行完毕后,再进入timer阶段。

四、总结

本文结合代码示例,对node的事件循环机制做了比较详细描述。通过这篇文章,应该可以了解浏览器的事件循环机制是怎样的,node的循环机制是怎样的,以及nextTick和micro队列的优先级,setTimout和setImmediate执行时机等一些容易混淆的知识点。文章中不足和不对之处,欢迎在评论区交流讨论,一起探索,谢谢。

更多编程相关知识,请访问:编程入门!!

위 내용은 nodejs의 이벤트 루프 메커니즘에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 掘金社区에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
자바 스크립트 행동 : 실제 예제 및 프로젝트자바 스크립트 행동 : 실제 예제 및 프로젝트Apr 19, 2025 am 12:13 AM

실제 세계에서 JavaScript의 응용 프로그램에는 프론트 엔드 및 백엔드 개발이 포함됩니다. 1) DOM 운영 및 이벤트 처리와 관련된 TODO 목록 응용 프로그램을 구축하여 프론트 엔드 애플리케이션을 표시합니다. 2) Node.js를 통해 RESTFULAPI를 구축하고 Express를 통해 백엔드 응용 프로그램을 시연하십시오.

JavaScript 및 웹 : 핵심 기능 및 사용 사례JavaScript 및 웹 : 핵심 기능 및 사용 사례Apr 18, 2025 am 12:19 AM

웹 개발에서 JavaScript의 주요 용도에는 클라이언트 상호 작용, 양식 검증 및 비동기 통신이 포함됩니다. 1) DOM 운영을 통한 동적 컨텐츠 업데이트 및 사용자 상호 작용; 2) 사용자가 사용자 경험을 향상시키기 위해 데이터를 제출하기 전에 클라이언트 확인이 수행됩니다. 3) 서버와의 진실한 통신은 Ajax 기술을 통해 달성됩니다.

JavaScript 엔진 이해 : 구현 세부 사항JavaScript 엔진 이해 : 구현 세부 사항Apr 17, 2025 am 12:05 AM

보다 효율적인 코드를 작성하고 성능 병목 현상 및 최적화 전략을 이해하는 데 도움이되기 때문에 JavaScript 엔진이 내부적으로 작동하는 방식을 이해하는 것은 개발자에게 중요합니다. 1) 엔진의 워크 플로에는 구문 분석, 컴파일 및 실행; 2) 실행 프로세스 중에 엔진은 인라인 캐시 및 숨겨진 클래스와 같은 동적 최적화를 수행합니다. 3) 모범 사례에는 글로벌 변수를 피하고 루프 최적화, Const 및 Lets 사용 및 과도한 폐쇄 사용을 피하는 것이 포함됩니다.

Python vs. JavaScript : 학습 곡선 및 사용 편의성Python vs. JavaScript : 학습 곡선 및 사용 편의성Apr 16, 2025 am 12:12 AM

Python은 부드러운 학습 곡선과 간결한 구문으로 초보자에게 더 적합합니다. JavaScript는 가파른 학습 곡선과 유연한 구문으로 프론트 엔드 개발에 적합합니다. 1. Python Syntax는 직관적이며 데이터 과학 및 백엔드 개발에 적합합니다. 2. JavaScript는 유연하며 프론트 엔드 및 서버 측 프로그래밍에서 널리 사용됩니다.

Python vs. JavaScript : 커뮤니티, 라이브러리 및 리소스Python vs. JavaScript : 커뮤니티, 라이브러리 및 리소스Apr 15, 2025 am 12:16 AM

Python과 JavaScript는 커뮤니티, 라이브러리 및 리소스 측면에서 고유 한 장점과 단점이 있습니다. 1) Python 커뮤니티는 친절하고 초보자에게 적합하지만 프론트 엔드 개발 리소스는 JavaScript만큼 풍부하지 않습니다. 2) Python은 데이터 과학 및 기계 학습 라이브러리에서 강력하며 JavaScript는 프론트 엔드 개발 라이브러리 및 프레임 워크에서 더 좋습니다. 3) 둘 다 풍부한 학습 리소스를 가지고 있지만 Python은 공식 문서로 시작하는 데 적합하지만 JavaScript는 MDNWebDocs에서 더 좋습니다. 선택은 프로젝트 요구와 개인적인 이익을 기반으로해야합니다.

C/C에서 JavaScript까지 : 모든 것이 어떻게 작동하는지C/C에서 JavaScript까지 : 모든 것이 어떻게 작동하는지Apr 14, 2025 am 12:05 AM

C/C에서 JavaScript로 전환하려면 동적 타이핑, 쓰레기 수집 및 비동기 프로그래밍으로 적응해야합니다. 1) C/C는 수동 메모리 관리가 필요한 정적으로 입력 한 언어이며 JavaScript는 동적으로 입력하고 쓰레기 수집이 자동으로 처리됩니다. 2) C/C를 기계 코드로 컴파일 해야하는 반면 JavaScript는 해석 된 언어입니다. 3) JavaScript는 폐쇄, 프로토 타입 체인 및 약속과 같은 개념을 소개하여 유연성과 비동기 프로그래밍 기능을 향상시킵니다.

JavaScript 엔진 : 구현 비교JavaScript 엔진 : 구현 비교Apr 13, 2025 am 12:05 AM

각각의 엔진의 구현 원리 및 최적화 전략이 다르기 때문에 JavaScript 엔진은 JavaScript 코드를 구문 분석하고 실행할 때 다른 영향을 미칩니다. 1. 어휘 분석 : 소스 코드를 어휘 단위로 변환합니다. 2. 문법 분석 : 추상 구문 트리를 생성합니다. 3. 최적화 및 컴파일 : JIT 컴파일러를 통해 기계 코드를 생성합니다. 4. 실행 : 기계 코드를 실행하십시오. V8 엔진은 즉각적인 컴파일 및 숨겨진 클래스를 통해 최적화하여 Spidermonkey는 유형 추론 시스템을 사용하여 동일한 코드에서 성능이 다른 성능을 제공합니다.

브라우저 너머 : 실제 세계의 JavaScript브라우저 너머 : 실제 세계의 JavaScriptApr 12, 2025 am 12:06 AM

실제 세계에서 JavaScript의 응용 프로그램에는 서버 측 프로그래밍, 모바일 애플리케이션 개발 및 사물 인터넷 제어가 포함됩니다. 1. 서버 측 프로그래밍은 Node.js를 통해 실현되며 동시 요청 처리에 적합합니다. 2. 모바일 애플리케이션 개발은 재교육을 통해 수행되며 크로스 플랫폼 배포를 지원합니다. 3. Johnny-Five 라이브러리를 통한 IoT 장치 제어에 사용되며 하드웨어 상호 작용에 적합합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.