この記事は、実際の開発と学習における nodejs についての個人的な理解です。将来の参考のためにまとめられています。インスピレーションになれば幸いです。
I/O: 入力/出力、システムの入力と出力。
システムは、人などの個人として理解できます。話すときは出力であり、聞くときは入力です。
ブロッキング I/O とノンブロッキング I/O の違いは、入力から出力までの期間に システムが他の入力を受信できるかどうかです。
次の 2 つの例は、ブロッキング I/O と非ブロッキング I/O が何であるかを示しています:1. クッキング
まず第一に、システムの範囲を決定する必要があります。この例では、食堂のおばさんとレストランのウェイターをシステムとみなします。入力は注文であり、出力は食べ物を提供しています。
次に、注文してから料理を提供するまでの間に他の人の注文を受け入れることができるかどうかで、それがブロッキング I/O であるかノンブロッキング I/O であるかを判断できます。 食堂のおばちゃんは、自分が注文している間は他の生徒の注文はできず、生徒が注文して料理を提供し終えてからでないと次の生徒の注文を受けられないので、食堂のおばちゃんはブロック中です。 I/O。 レストランのウェイターの場合、注文後、ゲストが料理を提供する前に次のゲストにサービスを提供できるため、ウェイターはノンブロッキング I/O を利用できます。2. 家事をする
洗濯をするとき、洗濯機の横で待つ必要はありません。この時間にそこに行くことができます 床を掃いて机の上を整理します 机が片付いて服を洗ったら、服を干してください 合計で 25 分しかかかりません。 衣類の洗濯は実際にはノンブロッキング I/O です。衣類を洗濯機に入れてから洗濯が終了するまでの間に、他のことを行うことができます。ノンブロッキング I/O によってパフォーマンスが向上する理由は、不必要な待ち時間を節約できるためです。
ノンブロッキング I/O を理解するための鍵は、:
node のシステム境界は main thread です。
下のアーキテクチャ図をスレッド保守に従って分割すると、左側の点線がnodejsスレッド、右側の点線がcスレッドになります。 ここで、nodejs スレッドはデータベースにクエリを実行する必要があります。これは典型的な I/O 操作です。I/O の結果を待たずに処理を続行します。他の操作: 計算のために大量の計算能力を他の C スレッドに分配します。 結果が出るまで待って、nodejs スレッドに返します。結果を取得する前に、nodejs スレッドは他の I/O 操作も実行できるため、ノンブロッキングです。nodejs thread は、左側の部分がウェイター、C スレッドがシェフに相当します。
つまり、ノードのノンブロッキング I/O は、c のワーカー スレッドを呼び出すことによって完了します。
C スレッドが結果を取得したときに、nodejs スレッドに通知するにはどうすればよいですか?答えはイベントドリブンです。
ブロッキング: プロセスは I/O 中にスリープし、I/O が完了するのを待ってから次の処理に進みます。 step;
Non-blocking: 関数は I/O 中にすぐに戻り、プロセスは I/O の完了を待ちません。
返された結果を確認するには、イベント駆動型を使用する必要があります。
いわゆるイベントドリブンは、フロントエンドのクリックイベントと同じものとして理解できます。最初にクリックイベントを書きますが、いつそれが行われるかわかりません。トリガーされたときのみ、メインスレッドにイベントドライバー関数を実行させます。
このモードはオブザーバー モードでもあります。つまり、最初にイベントをリッスンし、トリガーされたときにそれを実行します。 では、イベントドライブを実装するにはどうすればよいでしょうか?答えは非同期プログラミング です。
コールバック関数を使用するこの方法は、非同期プログラミングです。たとえば、次のコードはコールバック関数を通じて結果を取得します。 nodejs コールバック関数の最初のパラメータは error で、後続のパラメータは result です。どうしてそれをするの? 上記のような記述は非常に面倒で見苦しいです。そのため、promiseやasync/awaitという書き方が後から登場しました。 then または catch を実行すると、 。Promise の最終状態は、コールバック関数の実行結果によって決まります。 : 。 結果は同じです。言い換えれば、async/await は単なる Promise の構文糖です。 try catch はエラーをキャプチャします が、呼び出しスタックより上のエラーのみをキャプチャできることがわかっています。ただし、await を使用すると、コール スタック内のすべての関数のエラーをキャッチできます。 setTimeout などの別のイベント ループの呼び出しスタックでエラーがスローされた場合でも。 インタビュー コードを変換すると、コードが大幅に合理化されていることがわかります。 それが並列タスクの場合はどうなりますか? イベント ループは、nodejs のノンブロッキング I/O 機能を実現するための重要な基盤です。ノンブロッキング I/O とイベント ループは両方とも、 c ライブラリによって提供される機能です。 。 当然实际的事件要复杂的多,队列也不止一个,比如有一个文件操作对列,一个时间对列。 首先我们弄清楚了什么是非阻塞I/O,即遇到I/O立刻跳过执行后面的任务,不会等待I/O的结果。当I/O处理好了之后就会调用我们注册的事件处理函数,这就叫事件驱动。实现事件驱动就必须要用异步编程,异步编程是nodejs中最重要的环节,它从回调函数到promise,最后到async/await(使用同步的方法写异步逻辑)。 更多node相关知识,请访问:nodejs 教程!glob(__dirname+'/**/*', (err, res) => {
result = res
console.log('get result')
})
コールバック関数の形式指定
try {
interview(function () {
console.log('smile')
})
} catch(err) {
console.log('cry', err)
}
function interview(callback) {
setTimeout(() => {
if(Math.random() <p>実行後、エラーは捕捉されず、エラーがグローバルにスローされ、nodejs プログラム全体がクラッシュしました。 </p><p><img src="https://img.php.cn/upload/image/244/886/980/1657110712466688.png" title="1657110712466688.png" alt="nodejs のいくつかの主要なノードを理解するためのまとめと共有"></p><p> は、setTimeout がイベント ループを再度開くため、try catch ではキャプチャされません。イベント ループが開くたびに、コール スタック コンテキストが再生成されます。Try catch は前のイベントに属しますsetTimeout のコールバック関数が実行されると、コール スタックが異なります。この新しいコール スタックには try catch がないため、このエラーはグローバルにスローされ、キャッチできません。詳細については、この記事<a href="https://juejin.cn/post/6995749646366670855" target="_blank" title="https://juejin.cn/post/6995749646366670855">try catchに非同期キューを使用する場合の問題</a>を参照してください。 ######だから何をすべきか?エラーをパラメータとして使用します: </p><pre class="brush:php;toolbar:false">function interview(callback) {
setTimeout(() => {
if(Math.random() <p>ただし、これはさらに面倒で、コールバックで判断する必要があるため、成熟した規則が生成されます。最初のパラメータは err です。それが存在しない場合は、実行が成功したことを意味します。 </p><pre class="brush:php;toolbar:false">function interview(callback) {
setTimeout(() => {
if(Math.random() <p></p>非同期プロセス制御<h3 data-id="heading-5">
<strong></strong>nodejsのコールバック記述メソッドはコールバック領域を引き起こすだけでなく、</h3>非同期プロセス制御<p>の問題も引き起こします。 <strong></strong>非同期プロセス制御とは、主に、同時実行が発生した場合の同時実行ロジックの処理方法を指します。引き続き上記の例を使用しますが、同僚が 2 社の面接を受ける場合、2 社の面接に成功するまで 3 社目の面接は受けられません。では、このロジックはどのように記述すればよいでしょうか?変数 count をグローバルに 1 つ追加する必要があります: </p><pre class="brush:php;toolbar:false">var count = 0
interview((err) => {
if (err) {
return
}
count++
if (count >= 2) {
// 处理逻辑
}
})
interview((err) => {
if (err) {
return
}
count++
if (count >= 2) {
// 处理逻辑
}
})
現在のイベント ループでは結果を取得できませんが、将来のイベント ループでは結果が得られます。悪党の言うこととよく似ています。
約束はクソなだけでなく、状態マシンでもあります:
保留中
then & .catchconst pro = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('2')
}, 200)
})
console.log(pro) // 打印:Promise { <pending> }</pending>
解決済み状態の Promise は最初の を呼び出し、次に
コールバック地獄の問題を解決できますfunction interview() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve('success')
} else {
reject(new Error('fail'))
}
})
})
}
var promise = interview()
var promise1 = promise.then(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('accept')
}, 400)
})
})
var promise = interview()
.then(() => {
return interview()
})
.then(() => {
return interview()
})
.then(() => {
return interview()
})
.catch(e => {
console.log(e)
})
promise が地獄のコールバックを解決するだけである場合、promise は小さすぎて過小評価できません。promise の主な機能は非同期プロセス制御を解決することです。プロセス制御の問題。 2 つの企業に同時に面接したい場合:
function interview() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve('success')
} else {
reject(new Error('fail'))
}
})
})
}
promise
.all([interview(), interview()])
.then(() => {
console.log('smile')
})
// 如果有一家公司rejected,就catch
.catch(() => {
console.log('cry')
})
sync/await とは正確には何ですか:
console.log(async function() {
return 4
})
console.log(function() {
return new Promise((resolve, reject) => {
resolve(4)
})
})
try {
await interview(1)
await interview(2)
await interview(2)
} catch(e => {
console.log(e)
})
await Promise.all([interview(1), interview(2)])
nodejs のノンブロッキング I/0 のため、I/O 結果を取得するにはイベント駆動型メソッドを使用する必要があります。コールバック関数などの非同期プログラミングを使用する必要があります。では、結果を得るためにこれらのコールバック関数を実行するにはどうすればよいでしょうか?次に、イベントループを使用する必要があります。
<p><img src="https://img.php.cn/upload/image/722/472/129/165711073676826nodejs%20%E3%81%AE%E3%81%84%E3%81%8F%E3%81%A4%E3%81%8B%E3%81%AE%E4%B8%BB%E8%A6%81%E3%81%AA%E3%83%8E%E3%83%BC%E3%83%89%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E3%81%BE%E3%81%A8%E3%82%81%E3%81%A8%E5%85%B1%E6%9C%89" title="165711073676826nodejs のいくつかの主要なノードを理解するためのまとめと共有" alt="nodejs のいくつかの主要なノードを理解するためのまとめと共有"></p>
<p>代码演示:</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">const eventloop = {
queue: [],
loop() {
while(this.queue.length) {
const callback = this.queue.shift()
callback()
}
setTimeout(this.loop.bind(this), 50)
},
add(callback) {
this.queue.push(callback)
}
}
eventloop.loop()
setTimeout(() => {
eventloop.add(() => {
console.log('1')
})
}, 500)
setTimeout(() => {
eventloop.add(() => {
console.log('2')
})
}, 800)</pre><div class="contentsignin">ログイン後にコピー</div></div>
<p><code>setTimeout(this.loop.bind(this), 50)
保证了50ms就会去看队列中是否有回调,如果有就去执行。这样就形成了一个事件循环。const eventloop = {
queue: [],
fsQueue: [],
timerQueue: [],
loop() {
while(this.queue.length) {
const callback = this.queue.shift()
callback()
}
this.fsQueue.forEach(callback => {
if (done) {
callback()
}
})
setTimeout(this.loop.bind(this), 50)
},
add(callback) {
this.queue.push(callback)
}
}
总结
以上がnodejs のいくつかの主要なノードを理解するためのまとめと共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。