Cet article est une compréhension personnelle de nodejs dans le développement et l'apprentissage réels. Il est maintenant compilé pour référence future. Je serais honoré s'il pouvait vous inspirer.
E/S : Entrée/Sortie, l'entrée et la sortie d'un système.
Un système peut être compris comme un individu, comme une personne Lorsque vous parlez, c'est le résultat, et lorsque vous écoutez, c'est l'entrée.
La différence entre les E/S bloquantes et les E/S non bloquantes réside dans la capacité du système à recevoir d'autres entrées pendant la période allant de l'entrée à la sortie. Voici deux exemples pour illustrer ce que sont les E/S bloquantes et les E/S non bloquantes :
1 Préparer des repas
Tout d'abord, nous devons déterminer la portée d'un système. Dans cet exemple, la tante de la cafétéria considère cela comme un système avec le serveur du restaurant, l'entrée commande et la sortie sert la nourriture.
Ensuite, si vous pouvez accepter les commandes d'autres personnes entre la commande et le service de la nourriture, vous pouvez déterminer si cela bloque les E/S ou non. Pour la tante de la cafétéria, elle ne peut pas commander pour les autres étudiants lors de la commande. Ce n'est qu'après que l'étudiant a fini de commander et servi les plats qu'il peut accepter la commande de l'étudiant suivant, donc la tante de la cafétéria bloque les E/S.
Pour le serveur du restaurant, il peut servir le prochain invité après la commande et avant que le client ne serve le plat, le serveur dispose donc d'E/S non bloquantes.
2. Faites le ménageLorsque vous lavez des vêtements, vous n'avez pas besoin d'attendre la machine à laver. À ce moment-là, vous pouvez balayer le sol et organiser le bureau. sont lavés. À ce moment-là, allez étendre le linge, cela ne prend alors que 25 minutes au total.
La lessive est en fait une E/S non bloquante. Vous pouvez faire d'autres choses entre mettre les vêtements dans la machine à laver et terminer le lavage.
La raison pour laquelle les E/S non bloquantes peuvent améliorer les performances est qu'elles peuvent éviter des attentes inutiles.La clé pour comprendre les E/S non bloquantes est :
Déterminer une limite du système
pour les E/S. Ceci est très critique. Si le système est étendu, comme dans l'exemple de restaurant ci-dessus, si le système est étendu à l'ensemble du restaurant, alors le chef sera définitivement une E/S bloquante.. Si le schéma d'architecture ci-dessous est divisé en fonction de la maintenance des threads, la ligne pointillée à gauche est le thread nodejs et la ligne pointillée à droite est le thread c++.
Maintenant, le thread nodejs doit interroger la base de données. Il s'agit d'une opération d'E/S typique. Il n'attendra pas les résultats de l'E/S et continuera à traiter d'autres opérations. puissance de calcul à d’autres opérations thread C++ pour calculer.Attendez que le résultat soit publié et renvoyez-le au thread nodejs. Avant d'obtenir le résultat, le thread nodejs peut également effectuer d'autres opérations d'E/S, il est donc non bloquant.
nodejs threadéquivaut à ce que la partie gauche soit le serveur et le thread c++ étant le chef.
Ainsi, les E/S non bloquantes du nœud sont complétées en appelant des threads de travail C++.
Comment notifier le thread nodejs lorsque le thread c++ obtient le résultat ? La réponse est événementielle.
Event-driven
Non-blocking : La fonction revient immédiatement pendant I ; /O, et le processus n’attend pas la fin des E/S.
Ensuite, comment connaître le résultat renvoyé, vous devez utiliser event driver.
Le soi-disant Event-driven peut être compris comme la même chose que l'événement de clic frontal. J'écris d'abord un événement de clic, mais je ne sais pas quand il sera déclenché. Seulement quand il sera déclenché, le thread principal exécutera la fonction événementielle.
Ce mode est également un mode observateur, c'est-à-dire que j'écoute d'abord l'événement, puis je l'exécute lorsqu'il est déclenché. Alors, comment mettre en œuvre un drive événementiel ? La réponse est
Programmation asynchrone.
Programmation asynchrone
glob(__dirname+'/**/*', (err, res) => { result = res console.log('get result') })
Le premier paramètre de la fonction de rappel nodejs est l'erreur, et les paramètres suivants sont le résultat. Pourquoi faire ça ?
try { interview(function () { console.log('smile') }) } catch(err) { console.log('cry', err) } function interview(callback) { setTimeout(() => { if(Math.random() <p>Après l'exécution, il n'a pas été détecté et l'erreur a été générée globalement, provoquant le crash de l'ensemble du programme nodejs. </p><p><img src="https://img.php.cn/upload/image/244/886/980/1657110712466688.png" title="1657110712466688.png" alt="Résumé et partage pour comprendre plusieurs nœuds clés de nodejs"></p><p> n'est pas capturé par try catch car setTimeout rouvre la boucle d'événements. Chaque fois qu'une boucle d'événements est ouverte, un contexte de pile d'appels est régénéré try catch appartient à la pile d'appels de la boucle d'événements précédente et la fonction de rappel. de setTimeout est exécuté, la pile d'appels est différente. Il n'y a pas de try catch dans cette nouvelle pile d'appels, donc l'erreur est générée globalement et ne peut pas être interceptée. Pour plus de détails, veuillez vous référer à cet article <a href="https://juejin.cn/post/6995749646366670855" target="_blank" title="https://juejin.cn/post/6995749646366670855">Problèmes lors de l'utilisation de files d'attente asynchrones pour try catch</a>. </p><p>Alors que devons-nous faire ? Utilisez l'erreur comme paramètre : </p><pre class="brush:php;toolbar:false">function interview(callback) { setTimeout(() => { if(Math.random() <p> Mais c'est plus gênant, et cela doit être jugé dans le rappel, donc une convention mature est créée. Le premier paramètre est err. S'il n'existe pas, cela signifie que l'exécution est. réussi. </p><pre class="brush:php;toolbar:false">function interview(callback) { setTimeout(() => { if(Math.random() <h3 data-id="heading-5"><strong>Contrôle de processus asynchrone</strong></h3><p>La méthode d'écriture de rappel de nodejs apportera non seulement des zones de rappel, mais apportera également des problèmes de <strong>contrôle de processus asynchrone</strong>. </p><p>Le contrôle de processus asynchrone fait principalement référence à la façon de gérer la logique de concurrence lorsque la concurrence se produit. Toujours en utilisant l'exemple ci-dessus, si votre collègue interviewe deux entreprises, il ne sera pas interviewé par la troisième entreprise tant qu'il n'aura pas interviewé avec succès deux entreprises. Alors, comment écrire cette logique ? Il est nécessaire d'ajouter une variable count:</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) { // 处理逻辑 } })
globalement. Écrire comme ci-dessus est très gênant et moche. Par conséquent, les méthodes d’écriture promise et async/await sont apparues plus tard.
La boucle d'événements en cours ne peut pas obtenir le résultat, mais la boucle d'événements future vous donnera le résultat. C'est très similaire à ce que dirait un salaud.
la promesse n'est pas seulement un salaud, mais aussi une machine d'état :
const pro = new Promise((resolve, reject) => { setTimeout(() => { resolve('2') }, 200) }) console.log(pro) // 打印:Promise { <pending> }</pending>
renverra une nouvelle promesse L'état final de la promesse est déterminé par les résultats d'exécution des fonctions de rappel de then et catch :
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) }) })
résoudre le problème de l'enfer des rappels.
var promise = interview() .then(() => { return interview() }) .then(() => { return interview() }) .then(() => { return interview() }) .catch(e => { console.log(e) })
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') })
console.log(async function() { return 4 }) console.log(function() { return new Promise((resolve, reject) => { resolve(4) }) })
dépend de la pile d'appels et ne peut capturer que les erreurs situées au-dessus de la pile d'appels. Mais si vous utilisez wait, vous pouvez détecter des erreurs dans toutes les fonctions de la pile d'appels. Même si l'erreur est générée dans la pile d'appels d'une autre boucle d'événements, telle que setTimeout.
Après avoir transformé le code de l'entretien, vous pouvez voir que le code est très rationalisé.try { await interview(1) await interview(2) await interview(2) } catch(e => { console.log(e) })
await Promise.all([interview(1), interview(2)])
cette bibliothèque C++. libuv
代码演示:
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)
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) } }
首先我们弄清楚了什么是非阻塞I/O,即遇到I/O立刻跳过执行后面的任务,不会等待I/O的结果。当I/O处理好了之后就会调用我们注册的事件处理函数,这就叫事件驱动。实现事件驱动就必须要用异步编程,异步编程是nodejs中最重要的环节,它从回调函数到promise,最后到async/await(使用同步的方法写异步逻辑)。
更多node相关知识,请访问:nodejs 教程!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!