使用 Meteor 轻松开发实时网站

标签: 程序员 Meteor | 发表时间:2013-03-15 11:24 | 作者:童海波
出处:http://blog.jobbole.com

来源: IBM Developerworks

简介: 由于 Web 无处不在,即便是很小的数据交付延迟都有可能刺激到用户。他们希望数据即时更新。不幸的是,Web 技术无法实现这种实时访问。尽管数据访问正快速标准化为一些对象关系映射 (Object-Relational Mapping, ORM) 模型,但实时通信没有任何类似的解决方案。本文将讨论 Meteor,这是一个旨在解决此问题的激动人心的新 JavaScript 框架。

什么是 Meteor?

Meteor 是一种新的 JavaScript 框架,用于自动化和简化实时运行的 Web 应用程序的开发。它使用一个名为分布式数据协议 (Distributed Data Protocol, DDP) 的协议来处理实时通信,使用 WebSockets 的新 浏览器以及使用 Asynchronous JavaScript + XML (Ajax) 长轮询的旧浏览器来支持这种协议。在这两种情况下,浏览器到服务器的通信是透明的。

DDP 协议旨在处理 JavaScript Serialized Object Notation (JSON) 文档集合,使 JSON 文档容易创建、更新、删除、查询和访问。因为 DDP 是一种开源协议,所以您可将它连接到任何客户端或数据存储。它为 MongoDB 提供了开箱即使用支持。

事实上,Meteor 提供了两个 MongoDB 数据库:一个客户端缓存数据库和服务器上的一个 MongoDB 数据库。当一个用户更改一些数据时(例如通过单击  Save),在浏览器中运行的 JavaScript 代码会更新本地 MongoDB 中的相应的数据库项,然后向服务器发出一个 DDP 请求。该代码立即像操作已获得成功那样继续运行,因为它不需要等待服务器回复。与此同时,服务器在后台更新。如果服务器操作失败或返回一个意外结果,那么客户端 JavaScript 代码会依据从服务器新返回的数据立即进行调整。这种调整称为 延迟补偿,向用户提供了更高的认知速度。

显然,甚至连 Meteor 的模板系统也是为简化实时通信而设计的。在大多数 Web 框架中,您可以轻松地混合使用超文本标记语言 (HTML) 和代码,或者与 HTML 等效的标记,比如 HTML 抽象标记语言 (Haml)。这使您能够轻松地将来自数据库的动态值插入发送给用户的页面中。在这之后,您应该负责准备提供一个系统来观察对数据的更改,然后更新您的标记。但是,Meteor 中的模板系统用于记录访问了模板中的哪些数据,并自动回调,以便在底层数据更改时调用此 HTML,使实时模板变得更加简单快捷。

示例:链接流行度竞赛

Meteor 的模板功能可使众多实时应用程序更容易编写。例如,假设您希望创建一个的站点,用户可在其中输入链接(即统一资源定位符,URL),并投票肯定和否决它们,而且赢得流行度竞赛的 URL 会显示在一个列表顶部。通过使用 Meteor,您可以轻松地实时编写这样一个应用程序,以便用户可在其他用户投票时看见他们的 65 张选票。

安装 Meteor

要安装 Meteor,可以将 清单 1 中所示的代码键入到一个 Linux® 或 Mac OS® X 终端中。Meteor 不支持 Microsoft® Windows®。

清单 1. 安装 Meteor

curl https://install.meteor.com > install_meteor.sh
chmod u+x install_meteor.sh
./install_meteor.sh

现在您可创建一个新项目。

创建一个新项目

meteor 命令可自动化包含新项目创建过程中 Meteor 需要操作的一切内容的。键入 清单 2 中所示的命令,以便创建一个名为 realtime_links 的项目。

清单 2. 创建您的 Meteor 项目

meteor realtime_links
cd realtime_links

Meteor 创建了一个目录,其中包含一个 HTML 文件、一个 JavaScript 文件和一个级联样式表 (CSS) 文件。最后一个文件是一个标准 CSS 文件,但前两个值得讨论一下。您可以从  下载 一节下载 realtime_links.html 和 realtime_links.js 文件的完整版本。

realtime_links.html 文件

清单 3 显示了 realtime_links.html 文件的标头和正文片段。

清单 3. realtime_links.html 标头和正文片段

<head>
<title>Realtime Links Demo</title>
</head>

<body>
  {{> header }}
  {{> link_list }}
  {{> add_new_link }}
</body>

可以看到,HTML 模板的开头非常简单。无需担忧如何包含  BODY 标记、 DOCTYPE 修饰符甚至 JavaScript 和 CSS 文件。Meteor 会为您处理所有这些操作。有关 Meteor 的 JavaScript 和 CSS 包的更多信息,请参阅  参考资料,获取 Meteor 网站的链接。

{{> 语法表示 “呈现此模板”。可以看到,realtime_links.html 呈现了 3 个模板:

  • header 是一个简单头部,显示了数据库中的链接数量。
  • link_list 显示了链接的列表和它们的相关投票。
  • add_new_link 是添加新链接的表单。

清单 4 显示了  header 模板。

清单 4. realtime_links.html  header 模板

<template name="header">


<h1>The Link Collection</h1>

	<p>We currently have {{collection_size}} links.</p>

</template>

header 模板呈现了一个  h1 标记以及对集合大小的简短描述。 collection_size 方法是在 JavaScript 文件 realtime_links.js 中定义的(这将在  下一节 中详细讨论)。Meteor 自动观察某个模板插入了哪些数据片段。所以,在更新集合大小时, header 模板会自动更新。

请注意,这里使用的  {{ ... } 语法类似于 Ruby on Rails 中的  <%= ... %> 或 PHP 中的  <?= ... ?>。它可插入任意代码,所以能够以这种方式插入任何有用的动态表达式。

清单 5 显示了  link_list 模板。

清单 5. realtime_links.html  link_list 模板

<template name=
"link_list">

  <ul>

    {{#each links }}

      <li>  {{> link_detail }} </li>

    {{/each }}

  </ul>

</template>

如您所见,清单 5 中的代码是一个链接列表。realtime_links.js JavaScript 文件中的  links 方法提供了此列表。系统会向每个链接呈现 link_detail 模板。请注意,无需传递任何参数,因为 Handlebars 的  #each 循环会将每次迭代的当前上下文设置为当前对象。换句话说,会将  link_detail 模板的本地方法正确解释为每个链接对象的方法。

清单 6 显示了  link_detail 模板,它控制了为每个链接显示的数据。

清单 6. realtime_links.html  link_detail 模板

<template name="link_detail">


<div id="link-{{id}}">

    <h1>{{url}}</h1>

    <p><strong>Stats:</strong> up: {{thumbs_up}} down: {{thumbs_down}} 
net score: {{score}}</p>


<input type="button" value="Thumbs Up" 
 class="thumbs_up" url="{{url}}" />
    <input type="button" value="Thumbs Down" 
class="thumbs_down" url="{{url}}" />


</div>

</template>

h1 元素简单地显示当前链接的 URL。然后会提供一个间断的统计清单,其中包含一个链接被支持的次数、被否决的次数和它的净分数(也就是两个值的差)。最后,有两个按钮:一个用于投赞成或支持票,另一个用于投反对或否决票。JavaScript 文件定义这些按钮的行为,但是在深入介绍此主题前,还有一个模板需要了解。

清单 7 显示了  add_new_link 模板。

清单 7. realtime_links.html  add_new_link 模板

<template name="add_new_link">

  <div id="new_link_form">

    URL: <input id="url">

<input type="button" value="Click" id="add_url" />

  </div>

</template>

该模板只是一个文本输入字段和一个按钮,它们共同形成了向您列表中添加新 URL 的界面。

realtime_links.js 文件

realtime_links.js 中的 JavaScript 代码控制来自您程序的数据访问和事件回调,无论是在客户端还是在服务器上。 if (Meteor.is_client) 语句用于标记客户端部分, if (Meteor.is_server) 语句用于标记服务器部分。Meteor 提供了一种保护敏感代码的方式,阻止恶意客户端看到源代码。参见  参考资料 中的 Meteor 文档链接,了解有关的更多细节。

清单 8 显示了标头和链接列表帮助器函数。

清单 8. 标头和链接列表帮助器函数

				

Template.header.collection_size = function () {
return Links.find({}).count();
	};


	Template.link_list.links = function () {
return Links.find({}, {sort : {score: -1} });
	};

header 模板使用清单中的第一个帮助函数,该函数返回  links 集合的大小。 link_list 模板使用第二个帮助器函数,它返回从最高分到最低分排序的所有链接。

清单 9 拥有对  link_detail 模板的两个事件回调。

清单 9.  link_detail 事件回调

				
	Template.link_detail.events = 
{

'click input.thumbs_up' : function () {
Meteor.call('vote', this.url, 'thumbs_up');
},

  'click input.thumbs_down' : function 
() {Meteor.call('vote', this.url, 'thumbs_down');}

	};

每个事件回调处理一个支持或反对单击事件。在每种情况下,它们使用客户端上的  Meteor.call 在服务器上执行一次函数调用。可以看到从客户端对服务器执行调用很简单。例如,序列化会自动处理。

清单 10 显示了对用户可添加新链接的表单的事件回调。

清单 10. 对添加新链接表单的事件回调

				
  Template.add_new_link.events = {

    'click input#add_url' : 
dfunction () {

var new_url = $('#url').val();

      var url_row = Links.findOne( {url:new_url} );

      if(!url_row){

Links.insert( { url : new_url,
score: 0,
thumbs_up: 0,

thumbs_down: 0 });
      }
Meteor.call('vote', url, 'thumbs_up');

    }
  };

首先,该表单会尝试找到一个具有所请求 URL 的现有链接对象。如果它找到这样一个对象,那么它会将该请求统计为对这个现有链接对象的一次投票。如果未找到,那么它会创建一个新链接对象,并对这个新对象执行一次  thumbs_up 投票。

这部分代码演示了 Meteor 作为一种一流技术的优点和不足,它还不适合用于生产。如您所见,客户端可在  links 集合上调用 insert。尽管这对开发人员很有用,但从安全角度讲,这是一个问题。幸运的是,开发人员正在积极研究该代码的一个  auth 分支,这个分支可以实现强大的身份验证功能,同时仍然保持 Meteor 富有吸引力的很多强大功能和灵活性。

此外,需要认识到 Meteor 目前没有实现所有 MongoDB 功能。例如,Meteor 不支持 MongoDB upsert,该操作插入新数据或修改旧数据。如果 Meteor 支持 upsert,那么您可以编写 清单 11 中所示的函数。

清单 11. 一个使用 upsert 的假想的添加新链接表单事件回调

			
  Template.add_new_link.events = {

    'click input#add_url' : function () {

      var new_url = $('#url').val();

       Links.update( { url : new_url}, 
                     { $set: {url : new_url}, 
                       $inc: { votes : 1 } } , true );


    }
  };

如您所见,使用 upsert 的代码更短。它运行得可能更快,因为它仅需要与服务器执行一次往返传输。如果顺利的话,Meteor 很快就会实现对 upsert 和其他新功能的支持。

清单 12 中的代码在服务器上运行。它是一个可由客户端代码调用的方法。此方法( vote)允许客户端对一个流行的 URL 投 thumbs_up 或  thumbs_down 票。它使用 Mongo 的  $inc 运算符递增适当的投票计数器。它还在必要时递增或递减总数。 Meteor.startup 方法仅支持代码在服务器启动时运行。 Meteor.methods 函数然后定义可在客户端上调用  Meteor.call 的函数,如前面的  清单 9 中所述。

清单 12. 服务器端的  vote 方法代码

				
if (Meteor.is_server) {
    Meteor.startup(function () {
      Meteor.methods({
        vote: function (url, field){

new_obj = { $inc: { } };

 if(field =='thumbs_up'){
new_obj['$inc']['thumbs_up'] = 1;
 new_obj['$inc']['score'] = 1;
 }else{
new_obj['$inc']['thumbs_down'] = 1;
 new_obj['$inc']['score'] = -1;
                }

                Links.update( { url : url}, new_obj );

              }
      });
    });
}

与 清单 10 一样,您可在客户端上运行 清单 12 中的代码。但是,出于演示目的,将会在服务器上运行该代码。随着 Meteor 的安全模型得到改进,可能会将敏感的代码开发为服务器端函数,如下面清单所示。

查看您的应用程序的实际效果

现在可启动您的 Meteor 应用程序(如 清单 13 中所示)并查看它的实际效果。

清单 13. 启动您的系统

meteor

在启动后,Meteor 会在端口 3000 上运行。打开一个 Web 浏览器并访问 http://localhost:3000/。

如果在  Add a URL 下输入一个 URL 并单击  Add,则看到一个 URL 和评分  one。然后您可以单击  Thumbs Up 或  Thumbs Down 按钮对该 URL 进行投票。这会实时进行,而不会刷新页面。如果打开一个新 Web 浏览器,可在另一个窗口中执行相同操作,这时第一个窗口会立即更改。

当添加多个 URL 时,可以看到一个具有最高评分的 URL(分数被定义为支持票数减去反对票数)显示在最顶部。在投支持或反对票时,URL 会随着其评分更改而在列表中向上或向下移动。这是实时进行的,在输入投票时,多个浏览器上的多个用户都会收到相同的数据。

结束语

Meteor 是一个极具优势的 Web 框架,它包含了许多有趣的概念。它对实时数据的支持既富有吸引力又至关重要,特别是在考虑到其他技术实时支持充其量是一种事后行为时。随着实时交互变得对未来的 Web 更加重要,Meteor 轻松快速地实时处理复杂数据集的能力也将变得更加重要。

相关文章

使用 Meteor 轻松开发实时网站,首发于 博客 - 伯乐在线

相关 [meteor 开发 实时] 推荐:

使用 Meteor 轻松开发实时网站

- - 博客 - 伯乐在线
来源: IBM Developerworks. 简介: 由于 Web 无处不在,即便是很小的数据交付延迟都有可能刺激到用户. 不幸的是,Web 技术无法实现这种实时访问. 尽管数据访问正快速标准化为一些对象关系映射 (Object-Relational Mapping, ORM) 模型,但实时通信没有任何类似的解决方案.

网站开发只需数小时?Meteor 说这才是未来

- - 博客园_新闻
那个想要挑战过去数十年沿用至今的网站开发模式的新势力来了. Meteor 是从 YC 孵化而出的现代网站开发平台,希望构建一个极简的网站开发环境. 以往使用最好的工具、花费数周时间才能完成的网站,现在使用 Meteor 只需要几小时. 你可以利用周末或者一个咖啡无限续杯的编程马拉松活动日开发出一个完整的应用.

开源平台Meteor获投资,免费提供JS框架

- - ITeye资讯频道
开源平台 Meteor今日宣布A轮融资谈判结束,获得来自Andreessen Horowitz和Matrix Partners两家投资机构价值1120万美元的资金. 这是Andreessen Horowitz继 1亿美元投资Github之后又一次投资软件开发领域. Meteor公司提供的JavaScript框架开发平台目前免费使用,而且开源,可以用来创造类似于Google Docs的内容丰富的网页应用程序.

Flickr向开发者提供实时Web API

- 品味视界 - cnBeta.COM
Flickr今天向程序员推出了一个名叫Photo Hack Day的活动,释放了一批新的代码和API,让开发人员能够利用Flickr实时访问数据库从而构建新的应用,目前Flickr已经保有60亿张以上的图像. 新的API可以搜索每天上传的数以百万计照片并实时提供,这些数据还包含50多个机构例如美国宇航局,美国国会图书馆,美国和英国国家档案馆的更新.

基于mtcnn和facenet的实时人脸检测与识别系统开发 - 知乎

- -
简介:本文主要介绍了实时人脸检测与识别系统的详细方法. 该系统基于python/opencv2/tensorflow环境,实现了从摄像头读取视频,检测人脸,识别人脸的功能. 本系统代码地址: real time face detection and recognition. 人脸识别是计算机视觉研究领域的一个热点.

多屏时代的App实时同步,BackWire为开发者提供后台跨屏数据同步的BaaS解决方案

- - 互联网的那点事...
移动互联网时代,要想给用户提供一个完整、无缝的产品体验,开发者必须为自己的产品开发支持多个终端的应用. 同时在多终端环境下,还要解决各终端间数据实时同步的问题. 而昨天在InnoSpace 的首届DemoDay 上,就出现了一家为开发者提供App 多终端数据实时同步服务的创业公司: Backwire.

Android开发Tips

- - CSDN博客推荐文章
欢迎Follow我的 GitHub, 关注我的 CSDN.. 介绍一些, 在Android开发中, 会经常使用的小知识点.. submodule与git可以保持实时同步. 导入, 路径多于一个, 前面不添加冒号(:).. 使用PackageManager.. // 检查App是否安装 private boolean appInstalledOrNot(String uri) {.

Facebook的实时Hadoop系统

- wangjia - Solrex Shuffling
Facebook 在今年六月 SIGMOD 2011 上发表了一篇名为“Apache Hadoop Goes Realtime at Facebook”的会议论文 (pdf),介绍了 Facebook 为了打造一个实时的 HBase 系统使用到的独门秘技. 由于该论文提到的应用场景与小弟负责的系统要解决的问题域有相似之处,因而抽时间仔细阅读了这篇论文.

Storm 实时性分析

- - CSDN博客架构设计推荐文章
都说Storm是一个实时流处理系统,但Storm的实时性体现在什么方面呢. 首先有一个前提:这里的实时性和我们通常所说的实时系统(芯片+汇编或C编写的实时处理软件)的实时性肯定是没法比的,也不是同一个概念. 这里的实时性应该是一个相对的实时性(相对于Hadoop之类 ). 总结一下,Storm的实时性可能主要体现在:.

storm准实时应用

- - CSDN博客推荐文章
1 应用背景: 需要实时统计用户的登陆数,在线人数,活跃时间,下载等指标的数据,或者清洗后移到hdfs上.         1) 客户端产生数据---.         2) kafka-生产者实时采集数据(保留7天)-----.         3) storm实时消费数据,处理数据.         4)把实时数据统计结果缓存到memcached 中.