ホームページ ウェブフロントエンド jsチュートリアル Nodejs の実践経験:eventproxy モジュールが concurrency_node.js を制御する

Nodejs の実践経験:eventproxy モジュールが concurrency_node.js を制御する

May 16, 2016 pm 03:34 PM

目標

lesson4 プロジェクトを作成し、そこにコードを記述します。

コードのエントリ ポイントは app.js です。ノード app.js が呼び出されると、CNode (https://cnodejs.org/) コミュニティのホームページ (JSON 形式)。

出力例:

[
 {
  "title": "【公告】发招聘帖的同学留意一下这里",
  "href": "http://cnodejs.org/topic/541ed2d05e28155f24676a12",
  "comment1": "呵呵呵呵"
 },
 {
  "title": "发布一款 Sublime Text 下的 JavaScript 语法高亮插件",
  "href": "http://cnodejs.org/topic/54207e2efffeb6de3d61f68f",
  "comment1": "沙发!"
 }
]
ログイン後にコピー

チャレンジ

上記の目標に基づいて、comment1 の作成者とそのポイント値を cnode コミュニティに出力します。

例:


[
 {
  "title": "【公告】发招聘帖的同学留意一下这里",
  "href": "http://cnodejs.org/topic/541ed2d05e28155f24676a12",
  "comment1": "呵呵呵呵",
  "author1": "auser",
  "score1": 80
 },
 ...
]
ログイン後にコピー

知識ポイント

Node.js のコールバック地獄の美しさを体験してください

同時実行性を制御するツール、eventproxy の使用方法を学びます

コース内容

この章では、Node.js の最も素晴らしい部分である非同期同時実行について説明します。

前のレッスンでは、http get リクエストを開始するだけでホームページのコンテンツを取得するためにスーパーエージェントとチェリオを使用する方法を紹介しました。ただし、今回は各トピックの最初のコメントを取得する必要があるため、各トピックのリンクのリクエストを開始し、cheerio を使用して最初のコメントを取得する必要があります。


CNode には現在、ページごとに 40 のトピックがあるため、このレッスンの目標を達成するには 1 40 のリクエストを開始する必要があります。

後半の 40 リクエストを同時に開始しました :)、Node.js の同時実行モデルはマルチスレッドとは異なるため、これらの概念は放棄してください。より具体的に言うと、なぜ非同期が非同期なのか、なぜ Node.js はシングルスレッドでありながら同時実行できるのかなど、科学的な問題には立ち入りません。この側面に興味がある学生には、@puling の「Nine Lights and One Deep Node.js」:

http://book.douban.com/subject/25768396/ を強くお勧めします。

より洗練された友人の中には、プロミスやジェネレーターなどの概念について聞いたことがあるかもしれません。しかし、私はコールバックについてしか話せません。主な理由は、私が個人的にコールバックだけが好きなからです。

このコースでは 3 つのライブラリを使用する必要があります: superagent Cheerio eventproxy(

https://github.com/JacksonTian/eventproxy ) 足場の作業はご自身で行うことができ、プログラムを段階的に一緒に書いていきます。

最初の app.js は次のようになります

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);
 });

ログイン後にコピー
ノード app.js を実行します

出力は以下のようになります:

OK、これですべての URL のアドレスが取得できました。次に、これらのアドレスをすべてクロールすれば、Node.js は簡単に完了します。

クロールする前に、eventproxy ライブラリを導入する必要があります。

js で非同期を書いたことがある学生なら、2 つまたは 3 つのアドレスから同時に非同期でデータを取得し、データを取得した後にこれらのデータを一緒に使用したい場合、従来の書き方は自分でメンテナンスすることであることを知っているはずです。カウンタ。

最初に var count = 0 を定義し、次にクロールが成功するたびにカウントします。 3 つのソースからデータをキャプチャする場合、誰がこれらの非同期操作を最初に完了するかわからないため、キャプチャが成功するたびに count === 3 を確認します。値が true の場合、別の関数を使用して操作を続行します。

Eventproxy は、これらの非同期操作が完了したかどうかを管理するのに役立ちます。完了後、指定した処理関数が自動的に呼び出され、キャプチャされたデータがパラメーターとして渡されます。
イベントプロキシやカウンターを使用しないと仮定すると、3 つのソースをキャプチャする方法は次のとおりです:

// jquery の $.get メソッドを参照

$.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);
  });
 });
});

ログイン後にコピー
誰もが上記のコードを書いています。まず data1 を取得し、次に data2 を取得し、次に data3 を取得して、それらをファックして出力します。

しかし、実際には、これら 3 つのソースからのデータは並行して取得できることは誰もが考えているはずです。data2 の取得は data1 の完了に依存せず、同様に data3 も data2 に依存しません。


それで、カウンターを使用してそれを書きます。そして、それは次のように書かれます:

(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);
  }
 }
})();
ログイン後にコピー
たとえ醜いとしても、重要なのは、私が書いたコードが見栄えが良いということです。

eventproxy を使用する場合、次のように記述されます:

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);
 });
ログイン後にコピー
見た目はかなり進化したカウンターですね。

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 请求,然后利用得到的数据进行后期的处理工作,如何方便地判断数据已经全部并发获取得到,就可以用到该模块了。而模块不仅可以在服务端使用,也可以应用在客户端

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

JavaScriptの文字列文字を交換します JavaScriptの文字列文字を交換します Mar 11, 2025 am 12:07 AM

JavaScript文字列置換法とFAQの詳細な説明 この記事では、javaScriptの文字列文字を置き換える2つの方法について説明します:内部JavaScriptコードとWebページの内部HTML。 JavaScriptコード内の文字列を交換します 最も直接的な方法は、置換()メソッドを使用することです。 str = str.replace( "find"、 "置換"); この方法は、最初の一致のみを置き換えます。すべての一致を置き換えるには、正規表現を使用して、グローバルフラグGを追加します。 str = str.replace(/fi

8見事なjQueryページレイアウトプラグイン 8見事なjQueryページレイアウトプラグイン Mar 06, 2025 am 12:48 AM

楽なWebページレイアウトのためにjQueryを活用する:8本質的なプラグイン jQueryは、Webページのレイアウトを大幅に簡素化します。 この記事では、プロセスを合理化する8つの強力なjQueryプラグイン、特に手動のウェブサイトの作成に役立ちます

独自のAjax Webアプリケーションを構築します 独自のAjax Webアプリケーションを構築します Mar 09, 2025 am 12:11 AM

それで、あなたはここで、Ajaxと呼ばれるこのことについてすべてを学ぶ準備ができています。しかし、それは正確には何ですか? Ajaxという用語は、動的でインタラクティブなWebコンテンツを作成するために使用されるテクノロジーのゆるいグループ化を指します。 Ajaxという用語は、もともとJesse Jによって造られました

モバイル開発用のモバイルチートシート10個 モバイル開発用のモバイルチートシート10個 Mar 05, 2025 am 12:43 AM

この投稿は、Android、BlackBerry、およびiPhoneアプリ開発用の有用なチートシート、リファレンスガイド、クイックレシピ、コードスニペットをコンパイルします。 開発者がいないべきではありません! タッチジェスチャーリファレンスガイド(PDF) Desigの貴重なリソース

ソースビューアーでjQueryの知識を向上させます ソースビューアーでjQueryの知識を向上させます Mar 05, 2025 am 12:54 AM

jQueryは素晴らしいJavaScriptフレームワークです。ただし、他のライブラリと同様に、何が起こっているのかを発見するためにフードの下に入る必要がある場合があります。おそらく、バグをトレースしているか、jQueryが特定のUIをどのように達成するかに興味があるからです

独自のJavaScriptライブラリを作成および公開するにはどうすればよいですか? 独自のJavaScriptライブラリを作成および公開するにはどうすればよいですか? Mar 18, 2025 pm 03:12 PM

記事では、JavaScriptライブラリの作成、公開、および維持について説明し、計画、開発、テスト、ドキュメント、およびプロモーション戦略に焦点を当てています。

10 jQueryの楽しみとゲームプラグイン 10 jQueryの楽しみとゲームプラグイン Mar 08, 2025 am 12:42 AM

10の楽しいjQueryゲームプラグインして、あなたのウェブサイトをより魅力的にし、ユーザーの粘着性を高めます! Flashは依然としてカジュアルなWebゲームを開発するのに最適なソフトウェアですが、jQueryは驚くべき効果を生み出すこともできます。また、純粋なアクションフラッシュゲームに匹敵するものではありませんが、場合によってはブラウザで予期せぬ楽しみもできます。 jquery tic toeゲーム ゲームプログラミングの「Hello World」には、JQueryバージョンがあります。 ソースコード jQueryクレイジーワードコンポジションゲーム これは空白のゲームであり、単語の文脈を知らないために奇妙な結果を生み出すことができます。 ソースコード jquery鉱山の掃引ゲーム

jQuery Parallaxチュートリアル - アニメーションヘッダーの背景 jQuery Parallaxチュートリアル - アニメーションヘッダーの背景 Mar 08, 2025 am 12:39 AM

このチュートリアルでは、jQueryを使用して魅惑的な視差の背景効果を作成する方法を示しています。 見事な視覚的な深さを作成するレイヤー画像を備えたヘッダーバナーを構築します。 更新されたプラグインは、jQuery 1.6.4以降で動作します。 ダウンロードしてください

See all articles