重新学习node.js(草稿)

感觉又对node.js感兴趣了,因为想做socket,体验了java-bio的惨状,java上可以用vertx,但总是依赖IDE,结果又总是通过java去调自己写的js。java虽然有匿名类与lambda,但不是我喜欢的类型系统总憋脚地用又不像js只用几个概念的简洁。叛离node.js太久(前往java-nashron),发现是自己不适应太先进的理念吗?用node.js在文本编辑器里写就好。

曾经放弃node.js的原因,是觉得不成熟不稳定?但Java上的js可以很方便调用java的方法,静态语言减少很多调试。

学socket.io被官方文档迷糊住了,事实上还是得从解决问题入。试想最基础的通信,并不与web路由一样,而是维护一个客户端列表,可能数据库设定了不同客户的权限,之后都是自定义。而socket.io等框架总会被觉得有过度封装之嫌,它们的画蛇添足反而让人不能抓住其精髓,事实上从开发者角度又是对使用者最常用的特定场合的封装。感觉客户端列表应该自己维护,就像数据库的表,当需求复杂了,还不如直接暴露给查询。

现在js也深入思考有一些经验,比如一般的web服务都得重启,才能调试新写的代码,如何像jsp一样更改了刷新页面就能生效?在node里实现类似jsp,但不是模板引擎,而是路由模块,jsp是更新后请求时载入——也不对,是观察到文件系统下该文件发生改变,重新编译载入,这在node.js有watch模块,从前使用过。事实上从前在java-js这边使用了另一种模式,由于java-js上不带模块加载系统,我自己设计的模块加载系统编译成一个js文件,当更新服务器上的js文件,重新调用请求载入即可,不重启服务器。但这是全局的。在node.js上,我也得使用自己的模块系统,node.js自身的模块只能是一种辅助,类似于在nashron上加载java类。

服务器间相互保存了对方的ip地址,用http就可以通信了,与客户端浏览器通信得用socket。但系目标系统是否可用?比如你要更新系统。Erlang似乎就是在这样的环境里长大,所以有热更新能力。热更新,也只是上一次请求还是执行的之前的代码逻辑,新请求就是走新的流程逻辑了,但通信的数据结构不变。以前的前端页面一个url对应一个页面,也具有某种热更新能力,现在有太多单页富应用——也不是不可以,保持通信数据结构不变,只是有些违和。通信先通过队列将信息保存起来,等到目标客户有处理闲暇再顺次处理。一定要能先持久保存,不然通信的丢失是不可容忍的。

而且node.js本身是全异步的单线程的,没有线程冲突的危险,只是某些io的回调,如果嫌难看,得封装成一下,或使用现代代的表达式语法(糖),或yield/await之类。之前还一味拒绝着这些语法糖,只是考虑不兼容(新实现难度度),包括换行字符串,是多少语言想要的,能提高多少倍的生产力!然而除了自己的模块系统风格,很少跨引擎模块复用。公司内兼容IE8的js模块都没拿来在其它地方使用。

我想做一个编辑器,前端的树结构得实时与文件夹系统更新,需要watch,换来换去还是html最成熟完备好用,其它gui可能有性能加成。js没有类型不安全,类型也可能是束缚,因为类型并不一定符合你的使用习惯,会分散你的注意力。但我使用js有一定的规则习惯,我想做的就是加一个自己的类型系统,但语法不知道应该怎样比较美不冲突,js的语法目前看来是冲突最少、最方便使用的的妥协(因为经常忘记写逗号)。所以不应该从字符串上思考,而应该从内核模块去思考,代码生成好看的gui,顺便将类型检查做了。字符串层的语法不重要,可以变。但内核不变,gui展示可以减少很多冲突,并丰富展示关联。像markdown一样一边写一边展示。虽然有electron之类,但目前的趋势,直接建一个本地的web项目用浏览器查看就好。需要用socket去更新浏览器。

一切换回js,感觉自己的项目规模能提升100倍不止,用java写不得不先建立这样那样的类,虽然重构是很方便——但大部分同类型的重构在js里都不会发生,而且node.js比nashron调试方便(有大佬们支撑),更远比自创语言了。可能是从前node.js发展太快自己畏惧了,迷失了方向,害怕成为那浪潮中的小白鼠、牺牲品。但在浪潮中成长起来的大佬们,无论是经验还是金钱,都赚得盘满钵满了吧。

普通逃离node的原因是对前端的打包处理,现在我的自己的模块引擎。

学习socket.io

真正使用socket时,后端通常还是有不同的处理逻辑模块并列成列表,前端请求用type区分,其实这也就跟web-route差不多了,并列的东西都可以用树来细分,即命名空间。这个type其实就是socket.io的room吧。socket连接上后,其实内部就是web-route,前端就是一种ajax,但并不是回调,而是并列的状态,后端主动调用哪一个状态,什么时候调用都不一定的。通常分模块,某些状态集相互不干涉。

socket还有一点就是多用户彼此通信的问题。没有数据库建立的关联外,至少有广播类型,发送非自己的广播。有用户数据库关联,筛选发送,其实用户不在线,也会发到他的数据库去。

肯定是要建room的。服务端

服务端
var chat=io.of('/chat');//获得chat房间
chat.on('connection',function(socket){
	/*
	这其中,用chat.emit('event_name',data)是发给所有成员包括自己
	用socket.broadcast.emit('event_name',data)是发给非自己
	*/
});
其它,网络参考:
socket.broadcast.to('root').emit('event_name',data);//room所有的client端,除了自己
socket.broadcast.emit('event_name',data)//所有连接到server的client端
io.sockets.in('room').emit('event_name',data)//所有client端
io.sockets.emit('event_name',data);
io.of('namespace').in('room').emit()//

每一个room,或者说connection事件回调,就是用户空间,回调参数的socket代表具体的用户。可以和房间的所有人对话,或除自己以外的人对话。真正的mvvm,其实每个event的参数是必须符合特定类型的。传统的http回调,即ajax请求,只是不是全局区分的,没有返回多态类型,唯一的多态,是状态为未登录转调另一种方法。socket的通知其实更像mvvm的,如果对列表模型增加,则如何通知?如果是原子的,返回最新的状态,倒有点像mvc,只是返回的是数据,只是类型是更新原子数据。可能返回多个指令。甚至有点像jsonp。但页面的请求参数得带进去,即页面的所有状态得随请求带入,从而不用手动区分与操作DOM界面(感觉以前的ajax尝试都是错的)。

真正的模型修改只发生在后端。mvc,从视图的角度自己调用模型的方法,从模型的角度自己调用视图的方法,就是socket的双工。从前的web-http-ajax只是单向的询问,虽然可以做成前端mvc,即更新后立即请求最新的数据(但会有多次网络通信)。一个页面只有一个请求,查询与操作都是状态传递与指令。但是mvvm更简化,后端只剩模型,能模型的修改自动调用通知,如mve的几种model。要在后端建立类似vue的模型,房间不是匿名的,一个房间一个model,所有连接的客户端接受到通知。Value只有更新与通知两种,ArrayModel有几种更新,有两种、三种通知。如何将通知引入前端的业务逻辑,而不是单纯的观察?像vue,每次计算,都依赖统计(但不是单线程的)。另一种是个人的,后端模型映射到前端模型,也无法实现依赖统计,因为是异步的。 前端的socket事件是后端的属性,所以后端可以单线程mve,前端的socket事件是另一种模型。分离的特点是比如界面是一个列表或树,有自己的增删改查逻辑,但不由界面的按钮等直接控制,界面的按钮等只控制对中央唯一模型的修改,面模型的修改也不对具体界面修改,而是抽象地通知增删改,实现1-N的关系。视图接受到模型的变化通知(通常是有限的种类),但接受到通知,还有自己的处理方式。界面是无限外延彼此不相了解的,但大家都了解模型所以对模型观察(其实DOM元素事件的1-N倒不是必要的),通常界面元素是受某个模型的变化通知,但vue的依赖统计能将所有依赖统计出来。有一些特殊的模型比如树与列表,树可简化到列表,有增删改的动作,可以直接绑定为增删改的事件,还有长度统计,长度是原子的,长度也可作为computed的方式。观察者模式不是全局的,可以一层一层地封装成类,方法者是加入观察或移除观察(回调方法)。组件的生命周期,绑定与销毁,观察处理的逻辑也由具体组件自己去处理。

IDE中树的意义,是否要将整个目录树遍历出来,但文件太多目录太深,观察也不好观察,通常如idea会有懒加载,但懒加载还要观察文件系统有点麻烦。子文件或文件内容只是一次请求的返回,如果建立观察,或动态的观察。文件夹的内容是列表,文件的内容是是内容。但文件位置依赖文件夹,或者文件是独立的,它的路径是可改变的属性。 node.js中监听文件系统改变有多个watch,但官方的一般不太好,https://www.cnblogs.com/alisayuan/p/5355081.html ,之前一直使用watch模块,但既然推荐,则尝试chokidar。都是树型观察,与预期不一致。其实文件夹系统分目录和文件现在很好理解了,像编程语言中的结构体和值结点。我只观察展开的目录,观察打开的文件,不深入观察,只有用原生的。但fs.watch有bug与预期不一致?用node-watch:对于文件夹的观察,子文件夹内部的变化,相当于文件内容的变化,是update,而子文件/文件夹改名,则是删除与update,即新增也是update。对文件的观察,只有update与remove,remove之后就观察不到了。如果真是结构体,子文件夹内部变化不需要观察到,因为是引用类型,列表只观察列表的增加删除修改(修改简化为增删),文件观察内容变化,但引用可能需要观察位置变化。回头看原生的fs,修改文件会触发两次change,修改文件夹下的文件名,触发两次rename,前一次为最初名字,后一次是之后的名字;修改文件夹下的文件触发一次rename和一次change。子文件夹内部的修改也会触发change,与node-watch差不多!都不符合理想!是要自己去维护自己的文件系统吗?不用socket,只用前端,做树状的markdown

还要考虑node项目打包成独立可执行文件,虽然不是静态的,但好分发,不用每台电脑都去装个node。 这儿的资料https://www.jianshu.com/p/d044b8a8bf48

DOM编程,菜单比较好用,还没想好如何用进自己的mve,也许菜单是全局的,或某个局部的,只是展示位置这个属性在变。还有一个比较常用的功能是拖拽,各种拖拖拽是有利的。比如一上树,拖拽调整结构,其实树的子结点集合中每一个子结点维护了一个被观察的父节点,才能有观察模式。应该需要多了解以前包括jquery时代的各种控件库。

//路径问题
__dirname     //表示当前文件所在的目录的绝对路径
__filename     //表示当前文件的绝对路径
module.filename ==== __filename //等价
process.cwd()    //返回运行当前脚本的工作目录的路径,一般情况下不变,在process.chdir()后,或者shelljs.cd切换目录后会发生变化
process.chdir()   //改变工作目录
path.join(__dirname,'a','b');//E/node/1/a/b
path.resolve('./a','./b');//以应用程序为根路径

转载于:https://my.oschina.net/wy2010344/blog/3043232

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值