이 글에서는 Node.js의 비동기식에 대해 자세히 소개합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.
Node.js 비동기에 대해 피할 수 없는 두 가지가 있습니다: 비 차단 I/O 및 이벤트 루프입니다. Node.js가 고성능이라 할 수 있고 온라인 환경에서 사용할 수 있는 것은 바로 이 두 가지 때문입니다. 그럼 Node.js의 비동기 메커니즘과 사용법에 대해 알아볼까요? [추천 학습: "nodejs 튜토리얼"]
입력
/출력
입니다. 시스템의 Input
/Output
,一个系统的输入和输出。以点菜吃饭为例子:去饭堂点菜吃饭需要排队等待,在这个过程中,阿姨每次只能接待一个人,“点菜-阿姨抖勺装菜-把饭菜给到你”这个过程中阿姨并不能接收其他人的点菜,这个就是阻塞 I/O;而去餐馆点菜吃饭,去到餐馆就可以跟服务员你要吃番茄炒蛋,服务员记下来之后交给后厨,这时候来了另一桌人就把服务员招呼过去说想吃小龙虾,也就是说,在把菜给你上上来之前服务员接收了其他人的点菜,那这个就是非阻塞型 I/O。
理解非阻塞 I/O 的要点在于
Input
/Output
的系统。那在点菜吃饭这个例子中,一个进行 Input
/Output
的系统就是点餐-后厨(阿姨)处理-上菜这样一个能让你吃上饭的系统;点餐就是 Input
,上菜就是 Output
,在这个例子中判断两者是非阻塞型还是阻塞型的关键就在于在点菜上菜这个过程中能不能接受其它的点菜上菜。就好比你点了个佛跳墙,等上菜可能就要好久了,然后来的人都是点一些简单的菜品,一分钟炒一份炒粉的那种,可能就是来来回回几波人之后都还没能给你上菜。
而 Node.js 它是用来操纵计算机的,一些如读取文件之类的操作是非常耗时的,要是不能进行其它的 I/O,那么处理效率就很会很低了,这也是 Node.js 是非阻塞型 I/O 的一个原因。
Node.js 启动的时候会初始化由 libuv 提供的事件循环,每次的事件循环都包含6个阶段,这6个阶段会在每一次的事件循环当中按照下图当中的顺序反复执行,如下图:
timers
阶段:这个阶段执行 timer
(setTimeout
、setInterval
)的回调callbacks
阶段 :处理一些上一轮循环中的少数未执行的 I/O 回调idle
,prepare
阶段 :仅 Node 内部使用poll
阶段 :获取新的 I/O 事件, 适当的条件下 Node 将阻塞在这里check
阶段 :执行 setImmediate()
的回调close callbacks
阶段:执行 socket
的 close
事件回调每个阶段都有一个先入先出的(FIFO)的用于执行回调的队列,事件循环运行到每个阶段,都会从对应的回调队列中取出回调函数去执行,直到队列当中的内容耗尽,或者执行的回调数量达到了最大。
然后事件循环就会进入下一个阶段,然后又从下一个阶段对应的队列中取出回调函数执行,这样反复直到事件循环的最后一个阶段。而事件循环也会一个一个按照循环执行,直到进程结束。
事件循环当中的6个宏队列和微队列的关系如下:微队列(microtask
)在事件循环的各个阶段之间执行,或者说在事件循环的各个阶段对应的宏队列(macrotask
입력 및 출력
Blocking I/O와 Non-Blocking I/O의 차이점은 입력에서 출력까지의 기간 동안 시스템이 다른 입력을 받을 수 있는지 여부에 있습니다. 음식 주문을 예로 들어보겠습니다. 매점에서 음식을 주문하려면 줄을 서서 기다려야 합니다. 이 과정에서 이모는 한 번에 한 사람만 받을 수 있습니다. "음식 주문 - 이모" 숟가락을 흔들어 음식을 담는다 - "음식을 가져오는" 과정에서 이모님은 다른 사람의 주문을 받아들일 수 없습니다. 이는 음식을 주문하기 위해 식당에 갈 때 알 수 있습니다. 레스토랑에 가면 토마토 스크램블 에그를 먹고 싶다고 웨이터가 적어서 셰프에게 건네는데, 이때 다른 테이블 사람이 와서 웨이터를 불러 가재를 먹고 싶다고 말한다. 즉, 웨이터
가 음식을 제공하기 전에 다른 사람의 주문을 받은 것입니다. 그렇다면 이것은 논블로킹 I/O입니다. 비차단 I/O를 이해하는 열쇠는 🎜🎜🎜🎜입력
/출력
을 수행하는 시스템을 결정🎜하는 것입니다. 🎜🎜I/O 프로세스 중에 다른 I/O를 수행할 수 있는지 생각해 보세요🎜. 🎜음식 주문의 예에서 입력
/출력
을 수행하는 시스템은 주문 - 주방(이모)이 처리 - 서빙은 먹을 수 있는 시스템입니다. 주문은 입력
이고 서빙은 출력
입니다. 이 예에서 핵심은 두 가지가 무엇인지 결정하는 것입니다. 주문 및 서빙 과정에서 다른 주문 및 요리를 수락할 수 있는지 여부. 마치 부다 점프 오버 더 월(Buddha Jumps Over the Wall)을 주문하면 음식이 나오기까지 오랜 시간이 걸릴 수 있고, 그러면 오는 사람들은 튀길 수 있는 간단한 볶음면을 주문할 것입니다. 1분 정도 사람들이 오고 가는 바람에 아직 음식을 대접할 수 없었을 것 같아요. 🎜🎜그리고 Node.js는 컴퓨터를 제어하는 데 사용됩니다. 파일 읽기와 같은 일부 작업은 시간이 많이 걸립니다. 다른 I/O를 수행할 수 없으면 처리 효율성도 매우 낮습니다. 논블로킹 I/O의 이유. 🎜timers
단계: 이 단계는 timer
( setTimeout
, setInterval) 콜백🎜I/O <code>콜백
단계: 이전 주기에서 실행되지 않은 몇 가지 I/O를 처리합니다. 콜백🎜idle
, prepare 단계: Node에서 내부적으로만 사용됩니다.🎜poll
단계: 새로운 I/O 이벤트를 가져옵니다. Node는 적절한 조건에서 여기를 차단합니다.🎜check
단계: setImmediate()
의 콜백 실행🎜콜백 닫기
단계: close
이벤트 콜백 실행 of socket
🎜🎜각 단계에는 FIFO(선입선출) 기능이 있습니다. 콜백 실행을 위한 큐와 관련하여 이벤트 루프의 각 단계에서 콜백 함수는 해당 콜백 큐에서 꺼내어 큐의 내용이 소진되거나 실행된 콜백 수가 최대🎜에 도달할 때까지 실행됩니다. 🎜🎜이후 이벤트 루프는 다음 단계로 진입하고, 다음 단계에 해당하는 큐에서 콜백 함수를 꺼내어 실행하며, 이는 이벤트 루프의 마지막 단계까지 반복됩니다. 이벤트 루프도 프로세스가 끝날 때까지 하나씩 실행됩니다. 🎜🎜이벤트 루프의 6개 매크로 큐와 마이크로 큐의 관계는 다음과 같습니다. 마이크로 큐(microtask
)는 이벤트 루프의 다양한 단계 사이에서 실행되거나 이벤트 루프의 각 단계에서 해당 매크로가 실행됩니다. 큐 사이에서 실행되는 이벤트 루프(macrotask
). 🎜🎜🎜🎜🎜여기 특히 혼란스러운 버전 변경이 있습니다: 🎜setTimeout
, setInterval
및 setImmediate
)이 실행되면 I/O를 제외한 세 가지 중 하나 ), 즉시 마이크로태스크 대기열을 실행하고, 마이크로큐에 있는 모든 마이크로태스크를 실행한 후, 바로 지금 매크로큐로 돌아와서 다음 매크로태스크를 실행합니다. 이는 setTimeout
,setInterval
和 setImmediate
三者其中之一,不包括I/O)就立刻执行微任务队列,执行完微队列当中的所有微任务再回到刚才的宏队列执行下一个宏任务。这就跟浏览器端运行一致了。callback
error-first callback
node-style callback
error
,后面的参数才是结果。// 第一个参数是错误捕获 interview(function (err, res) { if (err) { console.log('cry') return; } console.log('smile') }) function interview(callback) { setTimeout(() => { if (Math.random() > 0.2) { callback(null, 'success') } else { callback(new Error('fail')) } }, 500) }
异步流程控制:回调地狱、异步并发等问题
npm
:async.js
;可以通过 async.js
来控制异步流程thunk
:一种编程方式Promise
Promise
是承诺的意思;当前事件循环得不到的结果,但未来的事件循环会给到你结果resolved
或 rejected
就不会改变pending
:初始状态,还没得到结果的状态fulfilled
/ resolved
:成功状态rejected
:失败状态链式调用:.then
和 .catch
resolved
状态的 Promise
会回调后面的第一个 .then
rejected
状态的 Promise
会回调后面的第一个 .catch
rejected
状态且后面没有 .catch
的 Promise
,都会造成浏览器/ Node 环境的全局错误// promise的状态转换以及通过then获取内容 const promise = new Promise((resolve, reject) => { setTimeout(function () { resolve(3); // reject(new Error(4)) }, 500) }) promise.then(function (result) { console.log(result) }).catch(function (err) { console.log(err) }) setTimeout(() => { console.log(promise) }, 800)
执行 then
和 catch
会返回一个新 Promise
,该 Promise
最终状态根据 then
和 catch
的回调函数的执行结果决定
throw
,该 Promise
是 rejected
状态return
,该 Promise
是 resolved
状态return
了一个 Promise
,该 Promise
会和回调函数 return
的 Promise
状态保持一致async
/await
async function
是 Promise
的语法糖封装await
关键字可以“暂停” async function
的执行await
关键字可以以同步的写法获取 Promise
的执行结果try-catch
可以获取 await
所得到的错误(async function () { await findJob() console.log('trip') })() async function findJob() { try { // 进行三轮面试 await interview(1); await interview(2); await interview(3); console.log('smile') } catch (e) { console.log('cry at ' + e.round) } } // 进行第round轮面试 function interview(round) { return new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() < 0.2) { const error = new Error('failed'); error.round = round; reject(error); } else { resolve('success'); } }, 500) }) }
这是一个穿越事件循环存在的 function
。
error
,后面的才是结果。Promise
是一个状态机,初始状态为 pending
,一旦确定状态为 resolved
或 rejected
就不会改变,可以通过 .then
和 .catch
进行链式调用。async
/await
브라우저 측 작업과 일치 합니다.
콜백
🎜오류 우선 콜백🎜🎜<code>노드 스타일 콜백
🎜🎜🎜🎜첫 번째 매개변수는 error
이고, 다음 매개변수는 결과입니다. 🎜🎜rrreee🎜비동기 프로세스 제어: 콜백 지옥, 비동기 동시성 및 기타 문제🎜🎜🎜npm
: async.js
를 전달할 수 있음 async.js code> 비동기 프로세스를 제어하려면🎜🎜<code>thunk
: 프로그래밍 방법🎜🎜Promise
🎜 🎜🎜 문자 그대로 이해할 수 있습니다. Promise
는 약속을 의미합니다. 현재 이벤트 루프는 결과를 얻을 수 없지만 미래의 이벤트 루프는 결과를 제공합니다🎜🎜이것은 상태 머신입니다. 상태가 해결됨
또는 거부
로 결정되면 변경되지 않습니다🎜🎜보류
: 초기 상태, 결과가 나오지 않은 상태 아직 획득함🎜🎜fulfilled
/ resolved
: 성공 상태 🎜🎜거부됨
: 실패 상태 🎜🎜🎜🎜🎜체인 호출: .then
및 .catch
🎜🎜🎜resolved
상태 Promise
는 첫 번째 .then
🎜를 콜백합니다. 🎜rejected
상태의 Promise
는 첫 번째 .catch
🎜🎜않은 모든 rejected
상태를 콜백합니다. .catch
의 Promise
를 따르면 브라우저/노드 환경에서 전역 오류가 발생합니다🎜🎜rrreee🎜then
및 catch를 실행하면
는 then
및 catch
의 콜백 함수 실행 결과에 따라 최종 상태가 결정되는 새로운 Promise
를 반환합니다. 🎜🎜 🎜콜백 함수가 throw
로 끝나는 경우 Promise
는 rejected
상태가 됩니다. 🎜🎜콜백 함수가 로 끝나는 경우 return
, Promise
는 해결
상태입니다 🎜🎜그러나 콜백 함수가 최종적으로 Promise
를 반환
하면 code>에서 Promise
는 콜백 함수 return
🎜🎜await
🎜🎜🎜async function
은 의 구문 설탕 패키지입니다. >비동기 프로그래밍에 대한 약속
🎜🎜궁극적인 솔루션 - 동기 방식으로 비동기 작성🎜🎜await
키워드는 비동기 함수
🎜🎜의 실행을 "일시 중지"할 수 있습니다. await
키워드를 사용할 수 있음 동기식 쓰기 방식으로 Promise
🎜🎜try-catch
의 실행 결과를 얻어 await에서 얻은 오류를 얻을 수 있음
🎜🎜🎜🎜rrreee🎜이벤트 루프를 통해 존재하는 함수
입니다. 🎜error
이고 그 결과는 다음과 같습니다. 🎜🎜Promise
는 🎜상태 머신🎜입니다. 초기 상태는 pending
입니다. 상태가 결정되면 해결됨
또는 가 됩니다. 거부됨
변경되지 않으며 .then
및 .catch
를 통해 연쇄 호출이 가능합니다. 🎜🎜async
/await
🎜동기식으로 비동기 작성🎜은 비동기 프로그래밍에 대한 궁극적인 솔루션입니다. 🎜🎜🎜더 많은 프로그래밍 관련 지식을 보려면 🎜프로그래밍 비디오🎜를 방문하세요! ! 🎜위 내용은 Node.js의 비동기성에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!