今天下午捣鼓了一下小应用,使用老赵的jscex给mongoose添加了Async 同步方法,感觉还不错,至少对我来说相当节省开发效率,分享一下。
给mongoose添加jscex的方法很简单,只需要使用老赵的 ”Jscex异步增强模块“进行异步操作绑定即可,什么是”Jscex异步增强模块“在此我就不缀述了,感兴趣的同学直接访问 Jscex异步增强模块 即可。这里仅贴出mongoose的异步操作绑定代码,代码比较简单,就不一一说明了。
先贴一个加载异步增强模块的代码,我事先用npm安装了jscex,命令如下” npm install jscex jscex-jit jscex-async”,详细请看赵姐夫的说明,链接地址:https://github.com/JeffreyZhao/jscex/blob/master/README-cn.md
var Jscex = require("jscex");require(“jscex-jit”).init(Jscex); require(“jscex-async”).init(Jscex); require(“./jscex-async-powerpack”).init(Jscex);
module.exports = Jscex;
有了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;
//真坑爹,mardown居然有小于号就显示不正确 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([‘save’,’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);
----------------------分割线----------------------------------
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](/user/gmail).com'; var task = saveUserAsync(user); 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](/user/gmail).com'; var task = removeUserAsync(user); 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](/user/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](/user/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'); }); }); }); }
}
不错不错,加油加油。不过好像测试的时候那段addEventListener有点没看懂是要干嘛的……还有addEventListener
的那个回调函数是通过this
访问的不是参数t,是不是文档哪里没有更新?
@hpf1908 其实要切换什么跟普通异步事件也没什么两样:
somethingAsync().on("complete", function () {
if (this.error) { ... } else { ... }
});
在Task.prototype
上补个on什么的是顺手的事情,你会发现和其他异步编程基本没区别。
@jeffz 恩,更新了通知一声,链式语法还是比较习惯的,另外异步增强里的fromCallback,我希望直接在返回值里挂一个叫_arguments的变量,这样我就不需要硬编码var splitAsync = Jscexify.fromCallback(split, "equals", "larger", “smaller”),取equals这种值
@jeffz 不是返回数组,像这样 var result = splitAsync(xxx); result._data = []; 除了显示设值外还另外把所有返回值做成数组形式挂在_data 下,这样的话给异步方法绑定同步写法,我就可以直接用fromCallback 就可以去取到所有返回值,当然你说的那样可读性更好也规范