노드 타이머

8787 단어 node타이머
JavaScript 는 단일 스 레 드 로 실행 되 며,비동기 작업 이 특히 중요 합 니 다.
엔진 이외 의 기능 만 사용 하면 외부 와 상호작용 을 하여 비동기 조작 을 형성 해 야 한다.비동기 동작 이 너무 많아 서 자바 스 크 립 트 는 비동기 문법 을 많이 제공 해 야 합 니 다.이것 은 마치 어떤 사람들 이 늘 타격 을 받 는 것 과 같다.그의 타격 저항 능력 은 반드시 매우 강해 져 야 한다.그렇지 않 으 면 그 는 끝장 이다.
Node 의 비동기 문법 은 브 라 우 저 보다 더 복잡 합 니 다.커 널 과 대화 할 수 있 기 때문에 전문 적 인 라 이브 러 리 libuv 를 만들어 야 합 니 다.이 라 이브 러 리 는 각종 반전 함수 의 실행 시간 을 책임 집 니 다.비동기 임 무 는 마지막 에 메 인 스 레 드 로 돌아 가 하나씩 줄 을 서서 실행 해 야 하기 때 문 입 니 다.

비동기 임 무 를 조율 하기 위해 노드 는 네 개의 타 이 머 를 제공 하여 임 무 를 지정 한 시간 에 실행 할 수 있 도록 했다.
  • setTimeout()
  • setInterval()
  • setImmediate()
  • process.nextTick()
  • 앞의 두 개 는 언어의 표준 이 고,뒤의 두 개 는 Node 만 의 것 이다.그것들의 서법 은 차이 가 많 지 않 고 작용 도 많 지 않 아 구별 하기 가 쉽 지 않다.
    당신 은 아래 코드 의 운행 결 과 를 말 할 수 있 습 니까?
    
    // test.js
    setTimeout(() => console.log(1));
    setImmediate(() => console.log(2));
    process.nextTick(() => console.log(3));
    Promise.resolve().then(() => console.log(4));
    (() => console.log(5))();
    운행 결 과 는 다음 과 같다.$ node test.js만약 네가 한 마디 로 옳다 고 말 할 수 있다 면 더 이상 볼 필요 가 없 을 것 이다.본 고 는 Node 가 각종 타 이 머 를 어떻게 처리 하 는 지,아니면 libuv 라 이브 러 리 가 어떻게 비동기 임 무 를 메 인 스 레 드 에서 수행 하 는 지 상세 하 게 설명 한다.
    1.동기 화 작업 과 비동기 작업
    우선 동기 화 작업 은 항상 비동기 작업 보다 일찍 실 행 됩 니 다.
    앞의 코드 는 마지막 줄 만 동기 화 작업 이기 때문에 가장 먼저 실 행 됩 니 다.(() => console.log(5))();2.이번 순환 과 2 차 순환
    비동기 임 무 는 두 가지 로 나 눌 수 있다.
    이번 라운드 에서 순환 하 는 비동기 퀘 스 트 추가
    순환 하 는 비동기 퀘 스 트 추가
    '순환'이란 이벤트 순환(event loop)을 말한다.이것 은 JavaScript 엔진 이 비동기 작업 을 처리 하 는 방식 입 니 다.나중에 자세히 설명 하 겠 습 니 다.여기 서 이해 하기 만 하면 이번 순환 은 반드시 다음 순환 보다 일찍 실행 하면 된다.
    Node 는 process.nextTick 과 Promise 의 리 셋 함 수 를 이번 라운드 순환 에 추가 하도록 규정 하고 있 습 니 다.즉,동기 화 작업 이 완료 되면 실행 을 시작 합 니 다.한편,setTimeout,setInterval,setImmediate 의 리 셋 함 수 는 차 순환 에 추 가 됩 니 다.
    즉,문장의 첫 번 째 줄 과 네 번 째 줄 은 반드시 첫 번 째 줄 과 두 번 째 줄 보다 일찍 실 행 될 것 이다.
    
    //     ,      
    setTimeout(() => console.log(1));
    setImmediate(() => console.log(2));
    //     ,      
    process.nextTick(() => console.log(3));
    Promise.resolve().then(() => console.log(4));
    3.process.nextTick()
    process.nextTick 이라는 이름 은 약간 오도 되 었 습 니 다.이것 은 이번 라운드 에서 순환 적 으로 실 행 된 것 이 고 모든 비동기 작업 에서 가장 빨리 실 행 된 것 입 니 다.

    Node 는 모든 동기 화 작업 을 수행 하고 process.nextTick 의 작업 대기 열 을 수행 합 니 다.그래서 다음 줄 코드 는 두 번 째 출력 결과 입 니 다.
    
    process.nextTick(() => console.log(3));
    기본적으로 비동기 임 무 를 가능 한 한 빨리 수행 하고 싶다 면 process.nextTick 을 사용 하 세 요.
    4.작은 임무
    언어 규격 에 따라Promise대상 의 반전 함수 가 비동기 작업 의'마이크로 작업'microtask대기 열 에 들 어 갑 니 다.
    마이크로 퀘 스 트 대기 열 은process.nextTick대기 열 뒤에 추가 되 며,이번 라운드 순환 에 도 속한다.그래서 아래 코드 는 항상 3 을 먼저 출력 하고 4 를 출력 합 니 다.
    
    process.nextTick(() => console.log(3));
    Promise.resolve().then(() => console.log(4));
    // 3
    // 4

    이전 대기 열 이 모두 비 워 져 야 다음 대기 열 이 실 행 됩 니 다.
    
    process.nextTick(() => console.log(1));
    Promise.resolve().then(() => console.log(2));
    process.nextTick(() => console.log(3));
    Promise.resolve().then(() => console.log(4));
    // 1
    // 3
    // 2
    // 4
    위의 코드 에서 모든process.nextTick의 리 턴 함수 가Promise보다 일찍 실 행 될 것 입 니 다.
    이로써 이번 순환 의 집행 순 서 는 끝났다.
    
        
    process.nextTick()
       
    5.사건 순환 의 개념
    다음은 다음 순환 의 실행 순 서 를 소개 합 니 다.이벤트 순환(event loop)이 무엇 인지 이해 해 야 합 니 다.
    노드 의공식 문서는 이렇게 소개 했다.
    “When Node.js starts, it initializes the event loop, processes the provided input script which may make async API calls, schedule timers, or call process.nextTick(), then begins processing the event loop.”
    이 단락 의 말 은 매우 중요 하 니 자세히 읽 어야 한다.그것 은 세 가지 의 미 를 표현 했다.
    우선,어떤 사람들 은 메 인 스 레 드 를 제외 하고 단독 이벤트 순환 스 레 드 가 존재 한다 고 생각한다.그렇지 않 습 니 다.메 인 스 레 드 만 있 고 이벤트 순환 은 메 인 스 레 드 에서 이 루어 집 니 다.
    그 다음 에 Node 가 스 크 립 트 를 실행 하기 시 작 했 을 때 이벤트 순환 을 초기 화 합 니 다.그러나 이 때 는 이벤트 순환 이 시작 되 지 않 았 고 다음 일 을 먼저 완성 합 니 다.
  • 동기 화 작업
  • 비동기 요청
  • 타이머 가 효력 이 발생 하 는 시간 을 계획 합 니 다
  • process.nextTick()등 을 실행 합 니 다.
    마지막 으로 위의 이 일 들 을 모두 끝내 고 사건 의 순환 이 본 격 적 으로 시작 되 었 다.
    6.사건 순환 의 6 단계
    사건 의 순환 은 무한 정 실 행 될 것 이 며,한 차례 또 한 차례 실 행 될 것 이다.비동기 작업 의 리 셋 함수 대기 열 이 비어 있어 야 실행 을 중단 할 수 있 습 니 다.
    매 라운드 의 사건 순환 은 6 단계 로 나 뉜 다.이 단계 들 은 순서대로 실 행 될 것 이다.
    timers
    I/O callbacks
    idle, prepare
    poll
    check
    close callbacks
    단계 마다 먼저 나 온 리 턴 함수 대기 열 이 있 습 니 다.한 단계 의 리 턴 함수 대기 열 이 비 워 졌 습 니 다.실행 할 리 턴 함수 가 모두 실행 되 어야 이벤트 순환 이 다음 단계 에 들 어 갈 수 있 습 니 다.

    다음은 각 단계 의 의 미 를 간단하게 소개 하고 공식 문 서 를 볼 수 있 으 며 libuv 의 소스 코드 해석 도 참고 할 수 있 습 니 다.
    (1)timers
    이것 은 타이머 단계 입 니 다.setTimeout()과 setInterval()을 처리 하 는 리 셋 함수 입 니 다.이 단계 에 들 어가 면 메 인 스 레 드 는 현재 시간,타이머 의 조건 을 만족 시 키 는 지 확인 합 니 다.만족 하면 리 셋 함 수 를 실행 합 니 다.그렇지 않 으 면 이 단 계 를 떠 납 니 다.
    (2)I/O callbacks
    다음 작업 의 리 셋 함 수 를 제외 하고 다른 리 셋 함 수 는 모두 이 단계 에서 실 행 됩 니 다.
  • setTimeout()과 setInterval()의 반전 함수
  • setImmediate()의 반전 함수
  • 요청 을 닫 는 데 사용 되 는 리 셋 함수,예 를 들 어 socket.on('close',...)
  • (3)idle, prepare
    이 단 계 는 libuv 내부 호출 만 가능 합 니 다.무시 할 수 있 습 니 다.
    (4)Poll
    이 단 계 는 폴 링 시간 으로 아직 돌아 오지 않 은 I/O 이 벤트 를 기다 리 는 데 사 용 됩 니 다.예 를 들 어 서버 의 응답,사용자 가 마 우 스 를 이동 하 는 등 입 니 다.
    이 단계 의 시간 은 비교적 길 것 이다.다른 비동기 작업(예 를 들 어 만 료 된 타이머)이 없 으 면 이 단계 에 머 물 러 I/O 요청 이 결 과 를 되 돌려 주 기 를 기다 릴 것 입 니 다.
    (5)check
    이 단 계 는 setImmediate()의 반전 함 수 를 실행 합 니 다.
    (6)close callbacks
    이 단 계 는 닫 기 요청 의 반전 함 수 를 실행 합 니 다.예 를 들 어socket.on('close', ...).
    7.사건 순환 의 예시
    다음은 공식 문서 에서 온 예시 이다.
    
    const fs = require('fs');
    const timeoutScheduled = Date.now();
    //      :100ms        
    setTimeout(() => {
     const delay = Date.now() - timeoutScheduled;
     console.log(`${delay}ms`);
    }, 100);
    //      :     200ms      
    fs.readFile('test.js', () => {
     const startCallback = Date.now();
     while (Date.now() - startCallback < 200) {
     //      
     }
    });
    위의 코드 는 두 개의 비동기 작업 이 있 습 니 다.하 나 는 100 ms 이후 에 실 행 된 타이머 이 고 하 나 는 최소 200 ms 의 파일 을 읽 어야 합 니 다.운행 결 과 는 무엇 입 니까?

    스 크 립 트 가 1 차 이벤트 순환 에 들 어간 후 만 료 된 타이머 도 없고 이미 실행 할 수 있 는 I/O 리 셋 함수 도 없 기 때문에 폴 단계 에 들 어가 서 커 널 이 파일 에서 읽 은 결 과 를 되 돌려 줄 때 까지 기 다 립 니 다.작은 파일 을 읽 는 것 은 일반적으로 100 ms 를 넘 지 않 기 때문에 타이머 가 만 료 되 기 전에 Poll 단계 에서 결 과 를 얻 을 수 있 기 때문에 계속 아래로 실 행 됩 니 다.
    2 차 이벤트 순환 은 만 료 된 타이머 가 없 지만 실행 가능 한 I/O 리 셋 함수 가 있 기 때문에 I/O callbacks 단계 에 들 어가 fs.readFile 의 리 셋 함 수 를 실행 합 니 다.이 반전 함 수 는 200 ms 가 필요 하 다.즉,그것 이 절반 까지 실 행 될 때 100 ms 의 타이머 가 만 료 된다 는 것 이다.그러나 이 반전 함수 가 실 행 될 때 까지 기 다 려 야 이 단 계 를 떠 날 수 있 습 니 다.
    3 차 이벤트 순환 은 만 료 된 타이머 가 있 기 때문에 timers 단계 에서 타 이 머 를 실행 합 니 다.마지막 출력 결 과 는 대략 200 여 밀리초 이다.
    8.setTimeout 과 setImmediatesetTimeouttimers 단계 에서 실행 되 기 때문에setImmediatecheck 단계 에서 실 행 됩 니 다.그래서 setTimeout 은 setImmediate 보다 일찍 완 성 됩 니 다.
    
    setTimeout(() => console.log(1));
    setImmediate(() => console.log(2));
    위의 코드 는 먼저 1 을 출력 하고 2 를 출력 해 야 하지만 실제 실행 할 때 결 과 는 확실 하지 않 고 때로는 2 를 먼저 출력 하고 1 을 출력 하기 도 한다.
    이것 은 setTimeout 의 두 번 째 매개 변 수 는 기본적으로 0 이기 때문이다.그러나 실제 노드 는 0 밀리초 도 되 지 않 고 최소 1 밀리초 가 필요 하 다.공식 문서 에 따 르 면 두 번 째 매개 변수의 수치 범 위 는 1 밀리초 에서 2147483647 밀리초 사이 이다.즉,setTimeout(f, 0)setTimeout(f, 1)과 같다.
    실제 실 행 될 때 이벤트 순환 에 들 어가 면 1 밀리초 가 될 수도 있 고 1 밀리초 가 안 될 수도 있 으 며 시스템 당시 상황 에 달 려 있다.1 밀리초 가 되 지 않 으 면 timers 단 계 는 건 너 뛰 고 check 단계 에 들 어가 setImmediate 의 리 셋 함 수 를 먼저 실행 합 니 다.
    그러나 아래 코드 는 반드시 2 를 먼저 출력 하고 1 을 출력 해 야 한다.
    
    const fs = require('fs');
    fs.readFile('test.js', () => {
     setTimeout(() => console.log(1));
     setImmediate(() => console.log(2));
    });
    위의 코드 는 I/O callbacks 단계 에 들 어가 고 check 단계 이 며 마지막 이 timers 단계 입 니 다.따라서 setImmediate 는 setTimeout 보다 일찍 실 행 됩 니 다.
    총결산
    위 에서 말씀 드 린 것 은 편집장 님 께 서 소개 해 주신 Node 타이머 에 관 한 지식 입 니 다.여러분 께 도움 이 되 셨 으 면 좋 겠 습 니 다.궁금 한 점 이 있 으 시 면 메 시 지 를 남 겨 주세요.편집장 님 께 서 바로 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

    좋은 웹페이지 즐겨찾기