标签 javascript 下的文章

简析Node.js的FastCGI实现

发表于 WebBuild

本文是我最近对Node.js学习过程中产生的一个想法,提出来和大家一起探讨。

##Node.js的HTTP服务器
使用Node.js可以非常容易的实现一个http服务,最简的例子如官方网站的示例:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');

这样就快速的搭建了一个监听在1337端口所有http请求的web服务。
但是,在真正的生产环境中,我们一般很少直接使用Node.js作为面向用户的最前端web服务器,原因主要有以下几种:

  • 基于Node.js单线程特性的原因,其健壮性的保证对开发人员要求比较高。
  • 服务器上可能已有其他http服务已占用80端口,而非80端口的web服务对用户显然不够友好。
  • Node.js对文件IO处理并没太大优势,如作为常规网站可能需同时响应图片等文件资源。
  • 分布式负载场景也是一个挑战。

所以,使用Node.js作为web服务更多可能是作为游戏服务器接口等类似场景,大多是处理不需用户直接访问且仅作数据交换的服务。

##基于Nginx作为前端机的Node.js web服务
基于上述原因,如果是使用Node.js搭建的网站形的产品,常规的使用方式是在Node.js的web服务前端放置另一个成熟的http服务器,如最常使用的是Nginx。
然后使用Nginx作为反向代理访问基于Node.js的web服务。如:

server{
    listen 80;
    server_name yekai.me;
    root /home/andy/wwwroot/yekai;

    location / {
        proxy_pass http://127.0.0.1:1337;
    }

    location ~ \.(gif|jpg|png|swf|ico|css|js)$ {
        root /home/andy/wwwroot/yekai/static;
    }
}

这样就比较好的解决了上面提出的几个问题。

##使用FastCGI协议通讯

- 阅读剩余部分 -

使用注释实现不支持javascript的浏览器功能优雅降级

发表于 WebBuild

首先看一段示例代码:
<div id="wrap">
<script type="text/javascript">
        document.write('<\!--');
</script>
<iframe src="xxx.html" frameborder="0" scrolling="no" width="320" height="384"></iframe>
<!-- DO NOT DELETE -->
</div>
<script type="text/javascript">
//xxx scroll、resize等条件执行下面滴
Ajax.get('xxx.php', function(ret){$('#wrap').html(ret)});
</script>

使用场景是这样的:就是页面在往下拖到一定距离滴时候会动态出来一块内容,但是为了保证不支持javascript的浏览器也能正常看到这块内容,需要做兼容处理。
可能有同学会说为啥不直接<noscript>搞定?是因为我们发现在中国这个奇葩环境下,我们的部分用户不是不支持js,而是jscript.dll等文件被破坏导致出现js支持但是解析不了的情况,所以出现了上面这个奇怪滴解决方案。
主要思路就是用js write出来html注释,使在js正常的情况下html代码不解析,然后使用正常的html注释的方式来关闭js写出来的注释(注意这里的注释开始符会被当做js写出来的注释的注释主体)使后续的html代码能正常解析。
不过,这样滴代码毕竟不是良好的代码风格,如果在项目中有使用html压缩等需要单独给功能形注释取消压缩,就如IE条件注释一样。

JavaScript那些事及第十一期web标准化交流会收获

发表于 WebBuild

本期w3ctech交流会主题是《我和JavaScript那些事儿》,是很泛的话题,有幸听到了老潘阿当rank月影音速MM等同学的分享,收获很大。

既然话题是我和JavaScript那些事儿,我也插播下我自己与JavaScript的那些事。我几乎也是05年左右第一次开始接触javascript,当然记得第一次alert出来hello的时候的那个兴奋。不过很惭愧的是,后来一直没怎么深入学习。月影大侠也是05年开始玩js,现在是js界叱咤风云的人物,我却还基础的JavaScript都玩不好,更惭愧的是现在还每天坐在月影旁边。后来工作了之后项目承担点与JavaScript打交道较少,并且有月影、JK及rank等同学写好的脚本库和组件,加上自己懒惰的性格,学习得也愈少了。

以一个用瀑布型都玩不好的菜鸟的理解,我认为JavaScript可以说是一个人小鬼大的语言,他的很多特性使得他容易上手又难以精通。并且他从出生起就带着很多不完善的东西,就像老道说的可惜大家已经用上并且爱上他了,所以再要严格的来次涅磐就不大可能了,后面rank同学也说到了组件开发中接口的设计就说到了设计中的这一点要一开始就考虑到。还有就是JavaScript规范的相对混乱,在基于浏览器的开发情况下:核心部分是ECMA来制定,而DOM又是W3C来规范,BOM部分实现上各个浏览器各自为政。不过个人觉得JavaScript最好玩的就是他的弱类型及对象的prototype,这是一种很好的抽象。这样一切传参和返回都可以是任意类型包括函数。就可以玩出看上去可能有点非主流但是很帅很流行的闭包、泛函这样的东西。

接下来说下在交流会上得到的收获。

首先是吕婷同学的分享,分享了她自己学习JavaScript的过程,ppt很漂亮。

然后老潘分享了《JavaScript闭包实例》,开始之前他自嘲说这个话题很枯燥,基本大家都会睡觉了。结果还好,好像就一哥们睡着了(不小心被我发现了)。老潘的分享很好,基本用很容易理解的方式向大家介绍了闭包及使用中内存泄漏等风险。

然后阿当用一个tabView实现来说明组件开发,用多步修正的方法来演示,很不错,一步步带领大家思考怎样满足多变的需求及优化余地。相信刚接触JavaScript的同学也能很好的理解。

接下来是rank的分享,分享的也是组件开发。从需求实现使用迭代等方面说明了组件开发中的重点及大家容易忽视的一些点。比如接口的实现,既要做到统一又方便后面升级开发、要做到内部高效率又要使使用者能容易使用。

很巧合的是这次虽说话题是《我和JavaScript那些事儿》,不过讨论最多的是组件实现这个具体的话题上,可能因为分享者带来的话题有关系吧。其中很有收获的一点是月影突然带来的一个关于组件实现的一个很独特的观点。可能是因为我们过多的关注(样式)组件最终的“展现”形式而没有用一种归类抽象的观点来看问题。就拿样式组件来说,其实质其实是通过交互带来的样式反馈。月影同时用Twitter来类比,比如我(类比页面中的某ELement)fo了@akira_cn(类比页面中另一个Element如button等),然后月影受到某刺激事件如女朋友的表扬(类比页面中click等事件,这个事件可以是任何的,onclick,onmouseover或者onhit什么的无所谓),然后月影发出通知:“MM表扬我了”(组件中建立好的联系通道),接着我作为一个fo对这个通知作出反映:“恭喜,恭喜!请客!”(类比出现popup框或者将某块常用说到的tabView中某块content块显示出来)。

这次交流会收获很大,也特别感谢soso提供的QQ公仔奖品,感谢腾讯的同学热情的招待,感谢所有分享者的准备,感谢所有参与交流的同学。boboRobin一上午就在忙碌的布置会场,大家给他俩来点掌声。

同时,因为某些特别的原因,在这里特别祝福波波,不管他做出怎样的决定,希望他以后的人生路更加精彩!也特别感谢他带给我们这么好的交流机会和平台。

最后,交流会下一期就是一周年生日了,祝福我们的交流会!

“邪恶”的opener

发表于 WebBuild

源于空空这条推

百度搜索结果页的那句 var location; 宛如神来之笔……


发散一下,然后在JerryQu及好奇同学的教导下知道了window.opener这个神奇的对象,然后发现它实在调皮又邪恶。他的location属性是个奇怪的东东,是外域虽然不可读却是可写的。
比如我们在页面中这样写(实例可以在http://hi.baidu.com/ivershuo_h右侧友情链接中点击最后一个那个名为“测试”的链接玩):

<script type="text/javascript">
var u = ['baidu.com', 'google.com', 'ivershuo.com'], 
i = 0 , 
l = u.length;
setInterval(function(
){
    opener.location = 'http://' + u[i];
    i++;
    i = (i == l?i = 0 : i);
},2000);
</script>


这样在所有链接到这个页面的页面就会出现不停跳转的情况,就算是使用后退按钮退回到先前的页面也一样(这个页面的opener将一直指向打开它的那个窗体)。这样对于一个普通的用户来说会觉得很奇怪。
如果用setTimeout及大延迟时间,然后用户又一直没关闭open(链接执行)页及opener页,且用户回到opener页继续查看,就会导致看到某个时间正在看的页面突然跳转而不知道在后面“捣乱”的却是来自外域的另外一个页面。
而如果针对某个特定的链接来源页(如搜索引擎搜索结果页),还可以预先埋上opener.location的hash到指定的页面id元素上,加上定时还可以让页面“跳舞”。
而如果是搜索引擎快照这样可能导致某些小风险同域风险的页面呢?
p.s:猜测因同步自己twitter显示到网页上的缘故,服务器ip在天朝某些范围处于和谐状态,建议用google reader订阅我的blog,RSS地址:http://feed.ivershuo.com/shuo

使用geolocation API定位你的访问者位置

发表于 WebBuild

今天要说一个跨省的好东西玩玩。

那就是geolocation,W3C对geolocation的解释是“defines an API that provides scripted access to geographical location information associated with the hosting device”。Firefox从3.5起就支持geolocation了,习惯赶时髦的opera也发布了一个支持geolocation的版本,几天前Chrome dev 5也正式支持geolocation了。如果你的浏览器被鄙视了也可以使用google gears的Geolocation API曲线救国来玩(关于这一点请参考JerryQu同学早一段时间写的文章)。于是记录和朋友们分享下。

如果你有兴趣可以使用上面提到的浏览器点击这里看个简单的demo

简单说下前端的实现吧,主要代码如下:

function displayPosition(position) {
    //得到两个值:position.coords.longitude(经度)、position.coords.latitude(维度)。
    /*任意鞣虐得到的经纬度信息来展示你想要的样子吧。
    */
}
navigator.geolocation.getCurrentPosition(displayPosition);


geolocation的原理就是收集你上网的终端设备的某些信息发送到特定的服务接口用来查询以获得你的地理信息,如果你是使用的是无线wifi上网的方式,发送的信息如JerryQu提到的一样,大致如下(Firefox下的抓包):

post http://www.google.com/loc/json
post_data='{"version":"1.1.0",
            "request_address":true,
            "access_token":"2:OLzIuqa-P8tZYOpu:Gu-LV8OcMFK28CVE",
            "wifi_towers":[
                {
                    "mac_address":"00-23-eb-b7-ef-70",
                    "ssid":"abc","signal_strength":-45
                },
                {
                    "mac_address":"00-23-eb-b7-ef-72",
                    "ssid":"abc_Guest","signal_strength":-48
                }
                ]
            }=';


返回的信息类似如下(可以查看我通过curl脚本模拟的数据 http://www.ivershuo.com/did/geolocation/loc.php):

{
    "location":
        {
            "latitude":40.0475799,
            "longitude":116.2947221,
            "address":{
                "country":"China",
                "country_code":"CN",
                "region":"Beijing",
                "city":"Beijing",
                "street":"Tangjialing Rd"
                },
            "accuracy":278.0
            }
        }


可以发现firefox也是使用的google的loc接口,如果你提供的access_token值为空或者是错误的在respone的时候会给你返回一个正确的access_token(该值是2周有效的)。wifi_towers包含了你的wifi信息数组用来判断你离热点们(?)的距离等信息。如果你使用的是有线上网的方式会发现传送的wifi_towers数组是空的,但是也会返回地理位置的值,应该是通过ip来返回的(因为我使用服务器脚本去请求该接口的时候返回的是服务器所在地的地理信息),所以偏差很大。现在还不知道是不是可以传送gps数据,有条件的同学可以试试在android手机上验证可以使用gps数据。

不过照前面的demo来看,就算是wifi的方式得到的位置信息还是有一定的偏差(这中间也有不同地图服务的定位信息的偏差),但是比ip获得的位置已经精确很多了。对位置信息精确度教高的web应用可以试点应用玩玩。

回到开头的那句话,大家不要担心跨省,因为浏览器在发送这个信息的时候会先要获得你的授权的。

p.s1:要使用geolocation:Firefox浏览器需要保证about:config中geo.enabled的值为true,chrome dev需要带参数“"--enable-geolocation"”启动。

p.s2:如果你也想构造数据请求google的loc接口,需要保证数据是以application/json的格式请求的。

天涯只看楼主的脚本

发表于 WebBuild

不是经常去天涯,刚才在天涯找了个文章,是楼主连载的,我想只看楼主,发现在天涯这个功能居然是收费的!没办法,万能的“猴子”出场了。

下面是js代码:

var author=document.getElementById('firstAuthor').getElementsByTagName('a')[0].innerHTML; //获取楼主id
var cont=document.getElementById('pContentDiv').getElementsByTagName('table'); //获取回复
for(var i=1;i&lt;cont.length;i++){
if(cont[i].getElementsByTagName('a')[0].innerHTML!=author){
cont[i].style.display='none'; //隐藏非楼主的帖子作者信息
var nextn=cont[i].nextSibling;
/*隐藏非楼主帖子*/
do{
if(nextn.nodeName=='#text'){
nextn.nodeValue='';
nextn=nextn.nextSibling;
}else{
nowbr=nextn;
nextn=nextn.nextSibling;
nowbr.parentNode.removeChild(nowbr);
}
}while(nextn.nodeName!='TABLE');
}
}

写到这里之后,和同学说,同学直接道将URL的“t”改成“o”就可以了,汗个~自己太愤青,忘记最快的路——问google了。于是去google了下,发现原来淘宝UED的空帷大哥早就写了这个greasemonkey脚本了,功能已经很完善了,我就不再写了(不过空帷大哥用正则判断的,我用DOM直接操作),哈哈!建议有需要的朋友直接去拿吧,呵呵。