Closed skinnyworm closed 9 years ago
@JacksonTian 有没有可能将wechat-api, wechat, co-wechat重构成一个项目? 我可以提供loopback部分的集成。
其实我内部也设计了一些类似语法糖的东东(权且叫API糖好了)。类似:
var Event = require('wechat').Event;
var events = new Event();
events.add('pic_weixin', function (message, req, res, next) {
// 弹出微信相册发图器的事件推送
});
var handle = Event.dispatch(events);
app.use('/wechat', wechat(config).event(handle).middlewarify());
@JacksonTian 好的,明白了,只是觉得现在几个项目的代码质量可能有待提高,提出的一些意见。不过如果您有时间仔细了解一下,可能会发现没那么容易。相同的功能,实现代码总量可以只有目前这个项目的1/3,且适用于不同应用场景, 比如API server, Web app, Mbass
我提出合并的初衷可能没有表达清楚,很大一部分在于code reuse, 而不是code copy。比如在一个Loopback的model api中同时完成api和responder功能,用户可以选择仅使用api或者是responder
var WechatService = require('../../index')
module.exports = function(Wechat){
WechatService.bindApi(Wechat);
WechatService.bindResponder(Wechat, function(responder){
responder
.always(function(message, cb){
this.messages.create({content: message}, cb);
})
.finally(function(message, reply){
reply({
msgType: 'text',
content: "Received :)"
});
});
});
};
拆分成小模块也就是为了基于module的级别进行code reuse呀。
不是太熟悉loopback,但是如果是connect或者express的话,其实也能写出很简洁的逻辑代码的。不过我基本上把这部分交给用户自己去管理复杂度了。
好的,理解了,以下是Loopback的api explorer, 用户可以在服务应用中直接使用model或绑定到restful api上
以群发消息为例,在现有API下,用loopback的话 你是怎么写的?
// 单个公众号, promisify
wechat.broadcast({type:'mpvideo', data: videoMsg}).promise.then(function(result){// result from 微信});
// 多个公众号, callback
Wechat.findById(appid, function(err, wechat){
if(err){return cb(err);}
wechat.broadcast({type:'mpvideo', data: videoMsg}, cb);
});
// 以上代码可以用async.seq优化
群发 POST http://server/wechats/{appid}/broadcast/ json: {"type": "mpvideo", "data": videoData}
查询群发消息 GET http://server/wechats/{appid}/broadcast/{messageId}/status
这个地方是用的客户端模式:
api.massSendText(content, receivers, callback);
和直接调用api并没有多大的差别吧。
对的,在api层面上,我仅仅封装了wechat-api,加上了对remoting的支持,重新定义了restful语意。不过我对api的实现还是有些意见的。
其实如果不封装wechat-api,我们可以在不需要写任何JS方法(除了accessToken部分)用remote datasource定义接口, 以下是对百度地图geocoder的定义
"baiduMap": {
"name": "baiduMap",
"connector": "rest",
"debug": "true",
"operations": [
{
"template": {
"method": "GET",
"url": "http://api.map.baidu.com/geocoder/v2/",
"headers": {
"accepts": "application/json",
"content-type": "application/json"
},
"query": {
"output": "json",
"ak": "XiZd42Z2Iv3eIoeGL1xxxxxxxxx",
"address": "{address}"
}
},
"functions": {
"geocode": [
"address"
]
}
}
]
}
定义好了,我们就可以直接使用
Baidu.geocode({address:'上海市淮海西路1080号'}, cb);
@JacksonTian 不好意思,我主要是对回复(respond)这部分有些想法而已, API部分虽然啰嗦,但接口用法还是一致的。
对wechat-api部分我觉得我这方面暂时不需要改什么。如果觉得不够promise,不够语义,另外封装即可。
对wechat这里,我原始提供的借口确实还有点原始。对业务逻辑的把握取决用户的驾驭能力,很有可能会写出比较罗嗦的代码出来。这部分欢迎一些新想法。
以下是我对wechat-api的group部分接口的封装,其中apiMethod属性就是wechat-api中的方法。但是我修改了部分api方法,特别是文件上传这部分,由于使用file不适合绑定到restful后上传,所以改用了stream可以直接pipe到微信服务器上。
{
"findGroups": {
"apiMethod": "getGroups",
"description": "获取分组列表",
"accepts": [],
"returns": {
"arg": "groups",
"type": "object",
"root":true
},
"http":{
"path": "/groups",
"verb": "get"
}
},
"createGroup":{
"apiMethod": "createGroup",
"description": "创建分组",
"accepts": [{
"arg": "name",
"type": "string",
"required": true,
"http":{
"source":"form"
}
}],
"returns": {
"arg": "group",
"type": "object",
"root":true
},
"http":{
"path": "/groups",
"verb": "post"
}
},
"updateGroup":{
"apiMethod": "updateGroup",
"description": "更新分组名字",
"accepts": [{
"arg": "groupid",
"type": "string",
"required": true
},{
"arg": "name",
"type": "string",
"required": true,
"http":{
"source":"form"
}
}],
"returns": {
"arg": "result",
"type": "object",
"root":true
},
"http":{
"path": "/groups/:groupid",
"verb": "put"
}
},
"deleteGroup":{
"apiMethod": "removeGroup",
"description": "删除分组",
"accepts": [{
"arg": "groupid",
"type": "number",
"required": true
}],
"returns": {
"arg": "result",
"type": "object",
"root":true
},
"http":{
"path": "/groups/:groupid",
"verb": "delete"
}
}
}
封装得挺好的。有点往config的方向去了。
@skinnyworm 比较赞同你的观点。
我也对这个项目的代码也不是很满意,原本准备fork的,但是现在是重新写了。 项目地址: https://github.com/JSSDKCN/node-weixin-api
目标就是你说的将所有的api集成到一个库里面。 由于现在API实现还不够完善,所以如果有兴趣可以一起增加自己需要的,一起改进代码。 基础功能应该是比较完善的,所以直接拿过来用就可以了。 具体实现参考原有的代码。
对于一些接收性质的http服务器API来说,只要参照expressjs标准去实现就可以了。 不必跟任何具体的服务相关联上。 欢迎提交代码。 :)
刚开始使用node, 可能有些建议不尽正确,请多包涵。
我觉得这个项目的设计还是有些可以改进的地方,其实分解开来看,在设计上可以更加模块化。
以Responder模块举例, api可以这样写
基于条件的回复, 可以有多个条件函数,选择策略可以基于最大匹配或者是最先匹配
最终回复,如果无任何符合条件的回复,就使用最终回复。默认的最终回复仅回复空,通过Api可以修改。
消息处理机制,不管回复是什么,可以配置一个消息处理函数,比如将消息加入队列或存到数据库中。
在以上的示例中,表示
以下是Responder的一个实现, 其中Responder.prototype.response 可以被middleware呼叫用于获得回复内容。