轻松给mongoose添加jscex的语法糖

突然发现好久没写blog了,从今天开始继续坚持写博客,下午捣鼓了一下小应用,使用老赵的jscex给mongoose添加了Async 同步方法,感觉还不错,至少对我来说相当节省开发效率。

给mongoose添加jscex的方法很简单,只需要使用老赵的 ”Jscex异步增强模块“进行异步操作绑定即可,什么是”Jscex异步增强模块“在此我就不缀述了,感兴趣的同学直接访问 Jscex异步增强模块 即可,这里仅贴出mongoose的异步操作绑定代码,代码比较简单,就不说明了。

var Jscex = require("jscex");

require("jscex-jit").init(Jscex);
require("jscex-async").init(Jscex);
require("./jscex-async-powerpack").init(Jscex);

module.exports = Jscex;

上面的代码是用于加载找姐夫的异步增强模块,我事先用npm安装了jscex,命令如下” npm install jscex jscex-jit jscex-async”,详细看赵姐夫的 jscex说明

var mongoose = require('mongoose'),
	Jscex = require('../plugins/jscex-start'),
	Model = mongoose.Model;

var Async = Jscex.Async;
var Task = Async.Task;
var Jscexify = Async.Jscexify;

var addSugarMethods = function(methods , obj){
	for(var i = 0 , len = methods.length; i < len ; i++){
		if(obj[methods[i]])
			obj[methods[i] + 'Async'] = Jscexify.fromStandard(obj[methods[i]]);
	}
}

module.exports = {
	init : function(){
		addSugarMethods(['find','remove'],Model.prototype);
	},
	model : function(name ,schema){
		mongoose.model(name, schema);
		var methods = ['find','remove','findById','findOne','count','distinct','create','update'];
		var model = mongoose.model(name);
		addSugarMethods(methods,model);
	}
}

上面的代码就是加语法糖的代码了,下面以node-club源码里的User 对象做个例子

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var modelAsync = require('./modelAsync');

var UserSchema = new Schema({
	//用户昵称
	name: {
		type: String,
		index: true
	},
	//用户登录名称:唯一
	loginname: {
		type: String
	},
	//登录密码
	pass: {
		type: String
	},
	//邮箱
	email: {
		type: String
	},
	//个人主页
	url: {
		type: String
	},
	//住址
	location: {
		type: String
	},
	//个性签名
	signature: {
		type: String
	},
	//个人简介
	profile: {
		type: String
	},
	//微薄
	weibo: {
		type: String
	},
	//头像
	avatar: {
		type: String
	},
	//被关注的人数
	follower_count: {
		type: Number,
		default: 0
	},
	//关注的人数
	following_count: {
		type: Number,
		default: 0
	},
	//创建时间
	create_at: {
		type: Date,
		default: Date.now
	},
	//更新时间
	update_at: {
		type: Date,
		default: Date.now
	},
	//是否活动状态
	active: {
		type: Boolean,
		default: true
	}
});

modelAsync.model('User', UserSchema);

上面的modelAsync即是前面异步绑定的模块,好,开始测试

var mongoose = require('mongoose'),
	config= require('../config').config,
	modelAsync = require('./modelAsync');

modelAsync.init();

mongoose.connect(config.db, function(err){
	if(err){
		console.log('connect to db error: ' + err.message);
		process.exit(1);
	}
});

// models
require('./user');

exports.User = mongoose.model('User');

上面代码取自node-club里的源码,至此就可以用同步的写法去获取数据了,测试代码如下,很简明易懂吧,当然如果你不喜欢这样的写法也可以继续使用异步的方式

var models      = require('../../models'),
	User = models.User,
	should = require('should'),
	Jscex = require('../../plugins/jscex-start');

module.exports = {

  'test updating documents async': function () {

  		var saveUserAsync = eval(Jscex.compile("async", function (user) {
		    $await(user.saveAsync());
		    var _user = $await(User.findAsync({ _id : user._id }));
		   	should.exist(_user);
		    _user.should.have.length(1);
		}));

	    var user = new User();

  		user.name      = 'flyhuang';
  		user.loginname = 'hpf1908';
  		user.pass      = '123456';
  		user.email     = 'hpf1908@gmail.com';

	    var task = saveUserAsync(user);

	    task.addEventListener("complete", function (t) {
		    if (t && t.error) {
		    	should.strictEqual(t.error, null);
		        console.log(t.error);
		        process.exit(1);
		    } else {
		    	console.log('done');
		        process.exit();
		    }
		});

		task.start();
  	},
  	'test delete documents async' : function(){

  		var removeUserAsync = eval(Jscex.compile("async", function (user) {
  			$await(user.saveAsync());
		    $await(User.removeAsync({ name : user.name }));
		    var _user = $await(User.findAsync({ name : user.name }));
		   	_user.should.be.empty;
		}));

		var user = new User();

  		user.name      = 'flyhuang';
  		user.loginname = 'hpf1908';
  		user.pass      = '123456';
  		user.email     = 'hpf1908@gmail.com';

	    var task = removeUserAsync(user);

	    task.addEventListener("complete", function (t) {
		    if (t && t.error) {
		    	should.strictEqual(t.error, null);
		        console.log(t.error);
		        process.exit(1);
		    } else {
		    	console.log('done');
		        process.exit();
		    }
		});

		task.start();
  	}
}

再贴一个用异步写法的例子,以作对比

var models      = require('../../models'),
	User = models.User,
	should = require('should');

module.exports = {

  'test updating documents': function () {

  		var user = new User();

  		user.name      = 'flyhuang';
  		user.loginname = 'hpf1908';
  		user.pass      = '123456';
  		user.email     = 'hpf1908@gmail.com';

	    user.save(function (err) {
	    	should.strictEqual(err, null);
	    	User.find({ _id : user._id },function(err , user){
	  			should.strictEqual(err, null);
	  			should.exist(user);
	  			user.should.have.length(1);

	  			console.log('done');
	  		});
	    });
  	},
  	'test delete documents' : function(){
  		var user = new User();

  		user.name      = 'flyhuang';
  		user.loginname = 'hpf1908';
  		user.pass      = '123456';
  		user.email     = 'hpf1908@gmail.com';

  		user.save(function (err) {
  			should.strictEqual(err, null);
	  		User.remove({ name : 'flyhuang' },function(err ){
	  			should.strictEqual(err, null);
	  			User.find({ name : 'flyhuang'},function(err , user){
		  			should.strictEqual(err, null);
		  			user.should.be.empty;
		  			console.log('done');
		  		});
	  		});
  		});
  	}
}

XSS:The only rule is no rule

转一篇来自iteye的帖子,看完彻底癫狂了,真是变态啊,以后如何防XSS攻击啊…

——————————-分割线 ————————————————

在2011年的BlackHat DC 2011大会上Ryan Barnett给出了一段关于XSS的示例javascript代码:

($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+($$=($_=!''+$)[_/_]+
$_[+$])])()[__[_/_]+__[_+~$]+$_[_]+$$](_/_)

这是一段完全合法的javascript代码,效果相当于alert(1)。它可以在大部分浏览器上运行。(虽然目前我测试过手头的浏览器都能运行,但理论上不能保证所有浏览器都能正确运行,原因见下文)

这段代码的好处(对于黑客)是,它不包含任何字符或数字,可以逃过某些过滤器的检查。比如说,如果假定一个AJAX请求将返回一个只包含数字的JSON,于是很可能会简单判断了一下其中不含字母就直接eval了,结果给黑客们留下了后门。上面的代码功能很简单,只是alert(1),但使用同样的原理,完全可以干出更复杂的事,例如alert(document.cookie)。更重要的是,这段代码再一次提醒我,黑客的想象力是无限的……正如Ryan Barnett的演讲标题:”XSS:The only rule is no rule”。 继续阅读 »

[转]初识mongodb-安装篇

MongoDB提供了部分系统的编译版本,但从研究学习以及线上不同依赖包的稳定性的目标,个人还是比较推荐从源代码编译安装的方式。MongoDB的源代码依赖了一些基础组件,如js引擎Spider Monkey,正则表达式引擎PCRE,安装构建工具Scons,以及C++的boost库等,因此编译还是有些麻烦的,realzyy的这篇文章已经比较详细的说明了编译的步骤,主要基于Redhat系统。在ubuntu上安装,还有几个注意点: 继续阅读 »

分享一个ie6中script节点加载的问题

记录一个在ie6中出现的问题

问题简介:

前段时间开发自测时ie6似乎什么问题都没有,结果一到测试环境就出现无法打开页面的错误?
一般情况下出现这种错误是因为在ie6下在dom ready之前对dom进行了操作,后来证实直接原因确实如此,但是为什么一到测试环境就出错了呢?

解决过程:

苦逼地找了半天,原来开发环境和测试环境的唯一差别在于开发环境加载script节点时增加了时间戳,不使用缓存,而测试环境没加时间戳,使用了缓存,问题纠结于此

原因:

在有缓存的情况下,ie6 script节点的onload事件不一定保证在代码执行完毕后才触发,并且是立即执行script的脚步,也就是说ie6在有缓存的情况下如下代码<script src = “xxx”></script>会变成同步的代码,如果代码中涉及到dom操作,那么就会出现这个问题

解决办法:很简单,涉及dom操作的代码显示调用dom ready之后再执行,犯了好低级的错误,唉,不过至少知其然了

js实现一个hashArray

最近在项目中考虑到性能的需要,需要在前台实现一个hashArray,即数组和map同时支持,大家都懂,map是为了快速查找,但是当你需要根据下标查找处于某个index位置的元素时,在js中就又得遍历了,于是用object和array组合实现了一个hashArray,用空间去换取时间

//实现hasnArrayMap
	var HashArrayMap = function(){
		this.items = [];
		this.map = {};
	}

	HashArrayMap.prototype.set =  function(key,value){
		var isFindInArray = false ;
		var obj ={key:key, value:value};
		for(var i = 0;i<this.items.length;i++){
			if(this.items[i].key == key) {
				obj.index = i;
				this.items[i] = obj;
				isFindInArray = true;
				break;
			}
		}
		if(!isFindInArray) {
			this.items.push(obj);
			obj.index = this.items.length - 1;
		}
		this.map[key] = value;
	}

	HashArrayMap.prototype.get =  function(){
		var isKey = typeof(arguments[0]) === 'string';
		if(isKey) {
			return this.map[arguments[0]];
		} else {
			if(typeof(arguments[0])=='number') {
				var index = parseInt(arguments[0]);
				if(index >= 0 && index < this.items.length) {
					return this.items[index].value;
				} else {
					return 'undefined';
				}
			} else {
				return 'undefined';
			}
		}
	}

	HashArrayMap.prototype.remove = function(){
		var isKey = typeof(arguments[0]) === 'string';
		if(isKey) {
			return this._remove(this.map[arguments[0]]);
		} else {
			if(typeof(arguments[0])=='number') {
				var index = parseInt(arguments[0]);
				if(index >= 0 && index < this.items.length) {
					return this._remove(this.items[index]);
				} else {
					return 'array over flow';
				}
			} else {
				return 'wrong arguments';
			}
		}
	}

	HashArrayMap.prototype._remove = function(obj){
		if(obj) {
			var index = obj.index,
				key = obj.key;
			this.items.splice(index ,1);
			if(this.map[key])
				delete this.map[key];
		}
		return true;
	}

	HashArrayMap.prototype.size = function(){
		return this.items.length;
	}

	/*
	var testArray = new SixDegree.HashArrayMap();
	testArray.set('name1' , '1');
	testArray.set('name2' , '2');
	testArray.set('name3' , '3');

	console.log(testArray.get('name1'));
	console.log(testArray.get('name2'));
	console.log(testArray.get('name3'));

	console.log(testArray.get(0));
	console.log(testArray.get(1));
	console.log(testArray.get(2));

	testArray.remove(0);

	for(var i=0 , len = testArray.size();i<len ; i++){
		console.log(testArray.get(i));
	}

	testArray.remove('name2');
	for(var i=0 , len = testArray.size();i<len ; i++){
		console.log(testArray.get(i));
	}
	*/

jQuery.sub 浅析

在看玉伯关于jQuery深度模块的化的文章时发现一个自己比较陌生的方法,查了一下,jQuery.sub 这个方法是1.5版本新增的方法,官方给出它的用途如下

There are two specific use cases for which jQuery.sub() was created. The first was for providing a painless way of overriding jQuery methods without completely destroying the original methods and another was for helping to do encapsulation and basic namespacing for jQuery plugins.

上面提到jQuery.sub这个方法主要用于两类特殊的情况,第一种情况是在不用污染jQuery对象原生方法的情况下提供一种干净的方式去覆盖扩展jQuery对象,另一种情况是帮助开发者封装和为jQuery插件构建一个命名空间,并分别给出了对应两种方式的例子 继续阅读 »

阮一峰的网络日志

该blog的作者是《黑客与画家》的译者,推荐一看

推荐理由:文章原创很多,涵盖范围较广,作者往往能深入浅出一些比较复杂的知识

blog地址:http://www.ruanyifeng.com/blog/

 

seajs – 全局map,调试利器

今天下午把最近一个项目的代码使用seajs来构建,发现seajs增加了一个非常好的插件:全局的Map映射,通过它你可以动态地将seajs加载的代码映射到任何网络路径上,这一点对于开发人员的好处是不言而喻的,假如你的所有js代码都是通过seajs引入的,那么意味着你可以非常轻松地得到seajs本地调试的支持,而不再需要依赖于fiddler、apache映射、配置host这些复杂的操作,详细参见这篇文章:http://seajs.com/docs/zh-cn/appendix-map-plugin.html

初略扫了一下插件代码,思路和自己想的一致,当seajs加载时发现url带有debug时,会开启插件调试工具,此时你可以输入你的map映射,如下图



输入后,seajs会记录下你的map映射文件路径,并将其写到名为seajs的cookie中,当初于debug模式时加载文件前,seajs会首先尝试读取该cookie,获取map映射,从而实现动态地调试切换,在搜狐时kola加载器也采取了这种方法,通过借助一个cookie 来切换线上和本地开发模式,效果很不错,看来在这一点上大家思路都是一致的,不过说起来kola使用这种方法还是比较超前的,嘿嘿….

杂记-前端mvc

underscore.js和backbone.js的兴起,带动了前端MVC的发展,国内首当其冲的是豆瓣说首先使用了这套组合,还是相当地给力的啊,看了下underscore.js的源码,又受打击了,随着以后浏览器的更新换代,对选择器的原生支持将越来越强的,sizzle.js 与它庞大的体积也许代价过高了,这样的话感觉 jQuery是到了拆分精简的时候,将jQuery模块化,配合seajs ,我理想的前端MVC是这样的组合

underscore.js + backbone.js +jQuery.js(部分功能)+ sea.js

在看前端MVC的过程中发现了腾讯一同事的blog,http://www.99css.com/archives/tag/cssgaga ,终于知道了cssgaga是何物了,怪不得重构给页面都带有cssgaga

IE的setTimeout函数传参

使用setTimeout做动画必不可免遇到IE不能传参的问题,一个解决方案记下来,来自 http://www.js8.in/593.html

(function(f){
         window.setTimeout =f(window.setTimeout);
         window.setInterval =f(window.setInterval);
     })(function(f){
         return function(c,t){
             var a=[].slice.call(arguments,2);
             return f(function(){
                 c.apply(this,a)},t)
             }
     });