Node.JS:
Node.js开源项目致力于提供一套编写高性能并发Web应用的JavaScript框架,完全事件驱动IO,基于V8 引擎,很适合中间件和WEB项目开发。
特点:
* 单线程事件模型,简单高效
* 基于活跃的高性能V8引擎
* 社区活跃,组件丰富
官方网址: http://nodejs.org/
项目网址: http://github.com/ry/node
中文社区: http://cnodejs.org/
NodeJs在 windows安装文档: https://github.com/joyent/node/wiki/Building-node.js-on-Cygwin-%28Windows%29
NodeJs中文文档: http://doc.open-open.com/view/74ffe3fa3eb24e23a61dc36ab95e93f0
http://wiki.grati.org/index.php?title=NodeJS%E4%B8%AD%E6%96%87%E6%96%87%E6%A1%A3#.E4.BF.A1.E6.81.AF
http://wenku.baidu.com/view/6f8335c34028915f804dc2be.html
引用网址:http://cnodejs.org/blog/?p=702
nodejs: 真正的一份代码,到处运行
现状: 冗余
在web开发中,我们是否常常会使用不同的编程语言实现相同的功能?
如一个文件上传功能,需要对上传文件进行文件格式限制。我们通常会使用后缀名做限制。
前端
为了用户体验,会在页面对用户选择的文件进行判断,合法才让用户可以上传。
<code>function is_filetype( filename, types) { types = types.split( ',') ; var pattern = '/.( '; for( var i=0 ; i<types.length; i++) { if( 0 != i) { pattern += '|'; } pattern += types[ i] .trim( ) ; } pattern += ') $'; return new RegExp( pattern, 'i') .test( filename) ; } ; // 此处省略N行代码 if( !is_filetype( $( '#uploadfile') .val( ) , 'doc,pdf,txt,wps,odf,md,png,gif,jpg') ) { can_submit = false; // 不允许上传 $( '#uploadfile') .val( '') ; alert( '只允许上传: ' + constant.RESUME_FILETYPES) ; } // 此处省略N行代码</code>
后端
由于担心恶意上传,无法避免地需要重新对用户上传的文件进行判断。
于是我又用python写了一个判断文件后缀的逻辑
<code>import re def is_filetype( filename, types) : types = types.split( ',') pattern = '/.( ' + '|'.join( [ t.strip( ) for t in types] ) + ') $'; return re.search( pattern, filename, re.I) != None # web request handler # 此处省略N行代码</code>
导致这样重复工作的原因是为什么?
- 前端永远不可信;
- 前端和后端使用不同的编程语言;
这样的冗余会带来什么代价?
- 修改业务逻辑,需要重复做2次:如突然发现少支持了 docx 文件类型,需要同时修改javascript代码和python代码
- 增加确保javascript代码和python代码业务逻辑一致的代价。需要分别写2种测试,unit test跑多一倍。
nodejs时代:DRY
一份代码,前端后端同时运行
<code>// constant.js ( function( exports) { exports.RESUME_FILETYPES = 'doc,docx,pdf,txt,wps,odf,md,png,gif,jpg'; } ) ( ( function( ) { if( typeof exports === 'undefined') { window.constant = { } ; return window.constant; } else { return exports; } } ) ( ) ) ; // util.js ( function( exports) { /** * 移除字符串两端的空白字符 * * @return { String} * @api public */ String.prototype.trim = function( ) { return this.replace( /( ^/s*) |( /s*$) /g, "") ; } ; /** * 判断是否自定类型的文件 * * @param { String} filename * @param { String} types, 多个类型使用,号分隔,如 doc,docx,txt * @return { Boolean} true or false * @api public */ var is_filetype = exports.is_filetype = function( filename, types) { types = types.split( ',') ; var pattern = '/.( '; for( var i=0 ; i<types.length; i++) { if( 0 != i) { pattern += '|'; } pattern += types[ i] .trim( ) ; } pattern += ') $'; return new RegExp( pattern, 'i') .test( filename) ; } ; } ) ( ( function( ) { if( typeof exports === 'undefined') { window.util = { } ; return window.util; } else { return exports; } } ) ( ) ) ;</code>
前端
<code><script src="/js/util.js"></script> <script src="/js/constant.js"></script> // 此处省略N行代码 if( !util.is_filetype( $( '#uploadfile') .val( ) , constant.RESUME_FILETYPES) ) { can_submit = false; // 不允许上传 $( '#uploadfile') .val( '') ; alert( '只允许上传: ' + constant.RESUME_FILETYPES) ; } // 此处省略N行代码</code>
后端
<code>var util = require( './public/js/util.js') , constant = require( './public/js/constant.js') ; app.post( '/resume/upload/:job_id', function( req, res, next) { req.form.complete( function( err, fields, files) { if( !util.is_filetype( filepath, constant.RESUME_FILETYPES) ) { // 由于客户端已做判断,所以这样的情况都是恶意上传的,直接提示 res.send( '文件格式错误: ' + filepath + ' , 请上传' + constant.RESUME_FILETYPES + '格式的文件') ; return; } // save file ... // 此处省略N行代码 } ) ; } ) ;</code>
wow,没冗余了吧!done
其他常用场景
- 常量定义
- 各种有用的工具模块,如字符串操作