


Expérience pratique de Nodejs : le module eventproxy contrôle concurrency_node.js
Objectif
Créez un projet de leçon4 et écrivez-y du code.
Le point d'entrée du code est app.js. Lorsque le nœud app.js est appelé, il affichera les titres, liens et chapitres de tous les sujets sur le CNode (https://cnodejs.org/) page d'accueil de la communauté. Un commentaire, au format json.
Exemple de sortie :
[ { "title": "【公告】发招聘帖的同学留意一下这里", "href": "http://cnodejs.org/topic/541ed2d05e28155f24676a12", "comment1": "呵呵呵呵" }, { "title": "发布一款 Sublime Text 下的 JavaScript 语法高亮插件", "href": "http://cnodejs.org/topic/54207e2efffeb6de3d61f68f", "comment1": "沙发!" } ]
Défi
Sur la base de l'objectif ci-dessus, affichez l'auteur du commentaire1 et sa valeur en points dans la communauté cnode.
Exemple :
[ { "title": "【公告】发招聘帖的同学留意一下这里", "href": "http://cnodejs.org/topic/541ed2d05e28155f24676a12", "comment1": "呵呵呵呵", "author1": "auser", "score1": 80 }, ... ]
Points de connaissances
Découvrez la beauté de l'enfer des rappels de Node.js
Apprenez à utiliser eventproxy, un outil pour contrôler la concurrence
Contenu du cours
Dans ce chapitre, nous abordons la partie la plus impressionnante de Node.js : la concurrence asynchrone.
Dans la leçon précédente, nous avons présenté comment utiliser superagent et cheerio pour obtenir le contenu de la page d'accueil. Il suffit de lancer une requête http get. Mais cette fois, nous devons récupérer le premier commentaire de chaque sujet, ce qui nous oblige à lancer une demande de lien de chaque sujet et à utiliser cheerio pour récupérer le premier commentaire.
CNode compte actuellement 40 sujets par page, nous devons donc lancer 1 40 requêtes pour atteindre notre objectif dans cette leçon.
Nous avons lancé les 40 dernières requêtes simultanément :), et nous ne rencontrerons pas de multi-threading ni de verrouillage. Le modèle de concurrence de Node.js est différent du multi-threading, alors abandonnez ces concepts. Pour être plus précis, je n'aborderai pas les questions scientifiques telles que pourquoi asynchrone est asynchrone et pourquoi Node.js peut être monothread mais concurrent. Pour les étudiants intéressés par cet aspect, je recommande vivement "Nine Lights and One Deep Node.js" de @puling : http://book.douban.com/subject/25768396/.
Certains amis plus sophistiqués ont peut-être entendu parler de concepts tels que les promesses et les générateurs. Mais pour ma part, je ne peux parler que de rappels. La raison principale est que personnellement, je n’aime que les rappels.
Nous devons utiliser trois bibliothèques pour ce cours : superagent cheerio eventproxy(https://github.com/JacksonTian/eventproxy )
Vous pouvez réaliser vous-même les travaux d’échafaudage et nous rédigerons ensemble le programme étape par étape.
Le premier app.js devrait ressembler à ceci
var eventproxy = require('eventproxy'); var superagent = require('superagent'); var cheerio = require('cheerio'); // url 模块是 Node.js 标准库里面的 // http://nodejs.org/api/url.html var url = require('url'); var cnodeUrl = 'https://cnodejs.org/'; superagent.get(cnodeUrl) .end(function (err, res) { if (err) { return console.error(err); } var topicUrls = []; var $ = cheerio.load(res.text); // 获取首页所有的链接 $('#topic_list .topic_title').each(function (idx, element) { var $element = $(element); // $element.attr('href') 本来的样子是 /topic/542acd7d5d28233425538b04 // 我们用 url.resolve 来自动推断出完整 url,变成 // https://cnodejs.org/topic/542acd7d5d28233425538b04 的形式 // 具体请看 http://nodejs.org/api/url.html#url_url_resolve_from_to 的示例 var href = url.resolve(cnodeUrl, $element.attr('href')); topicUrls.push(href); }); console.log(topicUrls); });
Exécuter le nœud app.js
Le résultat est le suivant :
OK, maintenant nous avons les adresses de toutes les URL. Ensuite, nous explorons toutes ces adresses et nous avons terminé avec Node.js, c'est aussi simple que cela.
Avant d'explorer, nous devons encore introduire la bibliothèque eventproxy.
Les étudiants qui ont écrit de manière asynchrone en js doivent tous savoir que si vous souhaitez obtenir des données de deux ou trois adresses simultanément et de manière asynchrone, et après avoir obtenu les données, utilisez ces données ensemble, la manière conventionnelle d'écrire est d'en conserver une vous-même. comptoir.
Définissez d’abord un var count = 0, puis comptez chaque fois que l’analyse réussit. Si vous souhaitez capturer des données provenant de trois sources, puisque vous ne savez pas qui effectuera ces opérations asynchrones en premier, chaque fois que la capture réussit, vérifiez le nombre === 3. Lorsque la valeur est vraie, utilisez une autre fonction pour continuer l'opération.
Eventproxy joue le rôle de ce compteur. Il vous aide à gérer si ces opérations asynchrones sont terminées. Une fois terminées, il appellera automatiquement la fonction de traitement que vous avez fournie et transmettra les données capturées en paramètres.
En supposant que nous n'utilisons pas de proxy d'événement ou de compteurs, la manière de capturer trois sources est la suivante :
// Reportez-vous à la méthode $.get de jquery
$.get("http://data1_source", function (data1) { // something $.get("http://data2_source", function (data2) { // something $.get("http://data3_source", function (data3) { // something var html = fuck(data1, data2, data3); render(html); }); }); });
Tout le monde a écrit le code ci-dessus. Obtenez d'abord data1, puis data2, puis data3, puis baisez-les et sortez.
Mais tout le monde aurait dû penser qu'en fait, les données de ces trois sources peuvent être obtenues en parallèle. L'acquisition de data2 ne dépend pas de la complétion de data1, et de même, data3 ne dépend pas de data2.
On utilise donc un compteur pour l'écrire, et il s'écrira ainsi :
(function () { var count = 0; var result = {}; $.get('http://data1_source', function (data) { result.data1 = data; count++; handle(); }); $.get('http://data2_source', function (data) { result.data2 = data; count++; handle(); }); $.get('http://data3_source', function (data) { result.data3 = data; count++; handle(); }); function handle() { if (count === 3) { var html = fuck(result.data1, result.data2, result.data3); render(html); } } })();
Même si c'est moche, ce n'est pas si moche que ça. L'essentiel est que le code que j'écris soit beau.
Si on utilisait eventproxy, cela s'écrirait ainsi :
var ep = new eventproxy(); ep.all('data1_event', 'data2_event', 'data3_event', function (data1, data2, data3) { var html = fuck(data1, data2, data3); render(html); }); $.get('http://data1_source', function (data) { ep.emit('data1_event', data); }); $.get('http://data2_source', function (data) { ep.emit('data2_event', data); }); $.get('http://data3_source', function (data) { ep.emit('data3_event', data); });
C'est bien mieux, non ? C'est juste un compteur avancé.
ep.all('data1_event', 'data2_event', 'data3_event', function (data1, data2, data3) {});
这一句,监听了三个事件,分别是 data1_event, data2_event, data3_event,每次当一个源的数据抓取完成时,就通过 ep.emit() 来告诉 ep 自己,某某事件已经完成了。
当三个事件未同时完成时,ep.emit() 调用之后不会做任何事;当三个事件都完成的时候,就会调用末尾的那个回调函数,来对它们进行统一处理。
eventproxy 提供了不少其他场景所需的 API,但最最常用的用法就是以上的这种,即:
先 var ep = new eventproxy(); 得到一个 eventproxy 实例。
告诉它你要监听哪些事件,并给它一个回调函数。ep.all('event1', 'event2', function (result1, result2) {})。
在适当的时候 ep.emit('event_name', eventData)。
eventproxy 这套处理异步并发的思路,我一直觉得就像是汇编里面的 goto 语句一样,程序逻辑在代码中随处跳跃。本来代码已经执行到 100 行了,突然 80 行的那个回调函数又开始工作了。如果你异步逻辑复杂点的话,80 行的这个函数完成之后,又激活了 60 行的另外一个函数。并发和嵌套的问题虽然解决了,但老祖宗们消灭了几十年的 goto 语句又回来了。
至于这套思想糟糕不糟糕,我个人倒是觉得还是不糟糕,用熟了看起来蛮清晰的。不过 js 这门渣渣语言本来就乱嘛,什么变量提升(http://www.cnblogs.com/damonlan/archive/2012/07/01/2553425.html )啊,没有 main 函数啊,变量作用域啊,数据类型常常简单得只有数字、字符串、哈希、数组啊,这一系列的问题,都不是事儿。
编程语言美丑啥的,咱心中有佛就好。
回到正题,之前我们已经得到了一个长度为 40 的 topicUrls 数组,里面包含了每条主题的链接。那么意味着,我们接下来要发出 40 个并发请求。我们需要用到 eventproxy 的 #after API。
大家自行学习一下这个 API 吧:https://github.com/JacksonTian/eventproxy#%E9%87%8D%E5%A4%8D%E5%BC%82%E6%AD%A5%E5%8D%8F%E4%BD%9C
我代码就直接贴了哈。
// 得到 topicUrls 之后 // 得到一个 eventproxy 的实例 var ep = new eventproxy(); // 命令 ep 重复监听 topicUrls.length 次(在这里也就是 40 次) `topic_html` 事件再行动 ep.after('topic_html', topicUrls.length, function (topics) { // topics 是个数组,包含了 40 次 ep.emit('topic_html', pair) 中的那 40 个 pair // 开始行动 topics = topics.map(function (topicPair) { // 接下来都是 jquery 的用法了 var topicUrl = topicPair[0]; var topicHtml = topicPair[1]; var $ = cheerio.load(topicHtml); return ({ title: $('.topic_full_title').text().trim(), href: topicUrl, comment1: $('.reply_content').eq(0).text().trim(), }); }); console.log('final:'); console.log(topics); }); topicUrls.forEach(function (topicUrl) { superagent.get(topicUrl) .end(function (err, res) { console.log('fetch ' + topicUrl + ' successful'); ep.emit('topic_html', [topicUrl, res.text]); }); });
输出长这样:
完整的代码请查看 lesson4 目录下的 app.js 文件
总结
今天介绍的 eventproxy 模块是控制并发用的,有时我们需要同时发送 N 个 http 请求,然后利用得到的数据进行后期的处理工作,如何方便地判断数据已经全部并发获取得到,就可以用到该模块了。而模块不仅可以在服务端使用,也可以应用在客户端

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Explication détaillée de la méthode de remplacement de la chaîne JavaScript et de la FAQ Cet article explorera deux façons de remplacer les caractères de chaîne dans JavaScript: le code JavaScript interne et le HTML interne pour les pages Web. Remplacer la chaîne dans le code JavaScript Le moyen le plus direct consiste à utiliser la méthode Remplace (): str = str.replace ("trouver", "remplacer"); Cette méthode remplace uniquement la première correspondance. Pour remplacer toutes les correspondances, utilisez une expression régulière et ajoutez le drapeau global G: str = str.replace (/ fi

Ce tutoriel vous montre comment intégrer une API de recherche Google personnalisée dans votre blog ou site Web, offrant une expérience de recherche plus raffinée que les fonctions de recherche de thème WordPress standard. C'est étonnamment facile! Vous pourrez restreindre les recherches à Y

Tirez parti de jQuery pour les dispositions de page Web sans effort: 8 plugins essentiels JQuery simplifie considérablement la mise en page de la page Web. Cet article met en évidence huit puissants plugins jQuery qui rationalisent le processus, particulièrement utile pour la création de sites Web manuels

Vous voici donc, prêt à tout savoir sur cette chose appelée Ajax. Mais qu'est-ce que c'est exactement? Le terme Ajax fait référence à un regroupement lâche de technologies utilisées pour créer un contenu Web interactif dynamique. Le terme Ajax, inventé à l'origine par Jesse J

Points de base Ceci dans JavaScript fait généralement référence à un objet qui "possède" la méthode, mais cela dépend de la façon dont la fonction est appelée. Lorsqu'il n'y a pas d'objet actuel, cela fait référence à l'objet global. Dans un navigateur Web, il est représenté par Window. Lorsque vous appelez une fonction, cela maintient l'objet global; mais lors de l'appel d'un constructeur d'objets ou de l'une de ses méthodes, cela fait référence à une instance de l'objet. Vous pouvez modifier le contexte de ceci en utilisant des méthodes telles que Call (), Appliquer () et Bind (). Ces méthodes appellent la fonction en utilisant la valeur et les paramètres donnés. JavaScript est un excellent langage de programmation. Il y a quelques années, cette phrase était

JQuery est un excellent cadre JavaScript. Cependant, comme pour n'importe quelle bibliothèque, il est parfois nécessaire de passer sous le capot pour découvrir ce qui se passe. C'est peut-être parce que vous tracez un bug ou que vous êtes simplement curieux de savoir comment jQuery réalise une interface utilisateur particulière

Ce message compile des feuilles de triche utiles, des guides de référence, des recettes rapides et des extraits de code pour le développement d'Android, BlackBerry et Iphone. Aucun développeur ne devrait être sans eux! Guide de référence sur les gestes touchés (PDF) Une ressource précieuse pour Desig

L'article discute de la création, de la publication et du maintien des bibliothèques JavaScript, en se concentrant sur la planification, le développement, les tests, la documentation et les stratégies de promotion.
