3D拓扑自动布局之Node.js篇

上篇将3D弹力布局的算法运行在Web Workers后台,这篇我们将进一步折腾,将算法运行到真正的后台:Node.js,事先申明Node.js篇和Web Workers篇一样,在这个应用场景下并不能提高性能,纯粹为了折腾好玩,当然也不会白玩,人生就在折腾中,只有折腾才能真正成长。

核心实现代码和Web Workers篇基本一致,唯一区别在于前后台交互的方式上,worker通过postMessage和addEventListener('message' 就可以发送和接收消息,对于真正分离前后台的Node.js自然没那么简单了,我采用了Socket.io通信框架,Socket.io让长连接通信变得无比简单,和Web Workers的通信几乎一样的容易了,Socket.io的用法下图一目了然:

Node.js后台代码如下,通过require引入HT和Socket.io相关类库,io = require('socket.io').listen(8036)构建出一个监听在8036端口的服务,通过io.sockets.on('connection'等着客户端页面来建立的socket通信,通过socket.on('moveMap',监听客户端发过来的图片节点拖拽变化信息进行同步,通过 socket.emit('result', result);发送自动布局算法的运算结果push到客户端。

io = require('socket.io').listen(8036);
ht = require('ht.js').ht;
require("ht-forcelayout.js");
reloadModel = require("util.js").reloadModel;    

io.sockets.on('connection', function (socket) {    
    var dataModel = new ht.DataModel(),
        forceLayout = new ht.layout.Force3dLayout(dataModel);

    forceLayout.onRelaxed = function(){    
        var result = {};
        dataModel.each(function(data){
           if(data instanceof ht.Node){
               result[data._id] = data.p3();
           } 
        });
        socket.emit('result', result);
    };
    forceLayout.start();

    socket.on('moveMap', function (moveMap) {
        dataModel.sm().cs();
        for(var id in moveMap){
            var data = dataModel.getDataById(id);
            if(data){
                data.p3(moveMap[id]);
                dataModel.sm().as(data);
            }
        }     
    });
    socket.on('reload', function (data) {
        reloadModel(dataModel, data);   
    });           
});

客户端的代码需要通过引入Socket.io客户端类库,通过socket = io.connect('http://localhost:8036/')链接服务器获得握手链接socket对象,剩下的代码就是同socket.emit发送客户端拖拽信息,以及socket.on监听服务器推送过来的自动布局结果:

            g3d.mi(function(evt){
                if(evt.kind === 'betweenMove'){                
                    moveMap = {};
                    g3d.sm().each(function(data){
                        if(data instanceof ht.Node){
                            moveMap[data._id] = data.p3();
                        }
                    });
                    socket.emit('moveMap', moveMap);                
                }
            }); 

            socket = io.connect('http://localhost:8036/');                              
            socket.on('result', function (result) {
                for(var id in result){
                    var data = dataModel.getDataById([id]);
                    if(data && !g3d.isSelected(data)){
                        data.p3(result[id]);
                    }                
                } 
            });

几个注意点:

1、首选和Web Workers一样,跑在Node.js的类库肯定不能操作window和document之类的页面特定元素对象,从这点说很多考虑不周全的类库会把自己限制死只能在页面主线程运行,这点HT for Web考虑得很周到,不仅ht.js包括所有ht-forcelayout.js插件都是可运在Web Workers和Node.js的非GUI环境,因为我也常需要ht.js运行在后台直接将DataModel的数据和前台进行JSON的数据格式转换存储。

2、Util.js定义的reloadModel函数我增加了this.reloadModel = reloadModel;的逻辑,这样才能在Node.js后台代码reloadModel = require("../util.js").reloadModel; 这样的方式得到该函数进行调用,细节可以参考 http://nodejs.org/api/modules.html 的章节

3、这个例子是有缺陷的,以下视频播放过程你会发现,我打开了两个页面,这样就会有两个socket分别连接后台Node.js,而Node.js默认是单线程的,如果正在一个请求函数密集运算处理,则其他请求只能排队等待处理,这也是视频中我拖拽一个页面布局是,另一个页面无法操作的原因。当然你可以改进demo,采用http://nodejs.org/api/cluster.html的cluster方式,实现真正的后台多核任务处理

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏hightopo

原 3D拓扑自动布局之Node.js篇

1033
来自专栏非著名程序员

基于开源项目搭建属于自己的技术堆栈

? 在技术面试的时候肯定都会问到使用了哪些第三方框架,为什么使用它而不用其他的。身边朋友就有这样的亲身经历: 面试官:你们项目中加载图片都是用的什么框架? 面...

2307
来自专栏大数据钻研

写给刚入门的前端工程师的前后端交互指南

作为刚接触前端的不久的童鞋,大家都会兴奋于CSS和JS所带来漂亮界面,然而,前端工程师除了UI重构外,还有非常重要的职责在正确的区域渲染出服务端的数据。毕竟,...

2677
来自专栏Coding01

使用 PubSubHubbub 制作 RSS 定时器 —— Laravel RSS (三)

由于我们使用 xpath 方式去抓取网站的内容,这些网站更新了内容,但它们不会实时告诉你它们更新了;所以「RSS 阅读器如何做到所谓的的「更新」呢?」

832
来自专栏微信公众号:Java团长

我整理的Java开源项目

772
来自专栏张善友的专栏

[腾讯社区开放平台].NET SDK基于New BSD协议开源

“QQ登录”使用户能使用QQ账号一键登录接入网站,大大降低了注册、登录的门槛。借助庞大的QQ用户群,给第三方网站带来更多新用户。已登录用户还可以将在第三方网站发...

1899
来自专栏程序猿DD

Spring Cloud构建微服务架构:服务网关(过滤器)【Dalston版】

在前两篇文章:服务网关(基础)、服务网关(路由配置)中,我们了解了Spring Cloud Zuul作为网关所具备的最基本功能:路由。本文我们将具体介绍一下Sp...

2875
来自专栏java一日一条

关于 Web 缓存的那些风流事儿

最近大家针对preload、HTTP/2 push和ServiceWorker的浏览器缓存实现展开了激烈的讨论,而这也引起了很多人的疑惑。

462
来自专栏张徐辰的专栏

十个书写Node.js REST API的最佳实践(上)

我们会通过本文介绍下书写Node.js REST API的最佳实践,包括各个主题,像是命名路由、认证、黑盒测试以及对相关资源使用合适的缓存头。

7800
来自专栏沃趣科技

等待事件统计视图 | 全方位认识 sys 系统库

在上一篇《内存分配统计视图 | 全方位认识 sys 系统库》中,我们介绍了sys 系统库如何查询内存事件统计信息和buffer pool统计信息,本期的内容先给...

710

扫码关注云+社区