node.js与dojo完美的融合-开发完全面向对象化
发布于 12 年前 作者 cory 9339 次浏览 最后一次编辑是 8 年前

最近学习了一下node.js,由于我是dojo出身,所以,觉得node.js并不是非常的面向对象化,并不满足面向对象的几个基本条件“封装”、“继承”、“多态”、“重载”等,虽然这些条件,JS是可以模拟出来的,但是重复的造轮子,会使得开发低下,性能堪忧。于是乎鄙人打算写一个node.js的OO module,然后看了一下dojo1.7的源码,发现原来,dojo1.7已经开始支持node.js了,这样就非常好了,我也不必去造轮子了。好了,废话少说,让我们来来看看,dojo是如何进入node.js的上下文的吧。 <br/> <br/>该文章分两个部分: <br/>1.我们来做一个小的test,来验证dojo是否已加入node.js的上下文中; <br/>2.我们把nodebeginner里面的一个上传图片的例子,用dojo来完成。 <br/> <br/>第一部分: <br/>开发环境我们可以采用eclipse来完成。将dojo包导入进去: <br/> <br/><img class=“aligncenter” src=“http://www.dojocn.org/data/attachment/forum/201112/18/123601znjunppdwyyer21d.jpg” alt=“Project结构图” /> <br/>最外层的dojo文件夹中放入的是dojo库。 <br/>我们在这个工程中,新建一个入口类Main.js <br/><pre><code>(function() { <br/>    this.dojoConfig = { <br/>        has: { <br/>            “host-node”: 1 <br/>        } <br/>    }; <br/>    require(“H:/Project/dojo_nodejs/dojo/dojo/dojo”); <br/>    define(“Main”, [], function() { <br/>        console.info(“Hello World!”); <br/>    }); <br/>})();</pre></code> <br/>这里说明一下,this表示的是node.js的上下文,这里给dojo设置host-node,因为dojo默认的模式是host-browser(浏览器窗口模式)。这里还要把dojo.js这个文件require进来,这样就OK啦。 <br/>运行效果: <br/><img class=“aligncenter” src=“http://www.dojocn.org/data/attachment/forum/201112/18/131719w8a9crieevherwt8.jpg” alt=“Hello World” /> <br/> <br/>这样,dojo就很轻松的融入到node.js的环境中了,是不是很简单^^¥。好了,下面在第二部分中我们来做一个上传文件的实例来表现dojo在开发node.js这一块强大的OO技术吧。(BTW:上传文件这个例子其实很简单,但是为了表现出用OO的形式来开发node.js,所以会故意写的有点复杂,请不要喷我<##>) <br/> <br/>第二部分: <br/>首先我们新建一个cory包,Main.js也需要稍微改一下,如下: <br/><pre><code>(function() { <br/>    this.dojoConfig = { <br/>        has: { <br/>            “host-node”: 1 <br/>        }, <br/>        paths: { <br/>            cory: “…/…/cory” <br/>        } <br/>    }; <br/>    require(“H:/Project/dojo_nodejs/dojo/dojo/dojo”); <br/>    define(“Main”, [], function() { <br/>        console.info(“Hello World!”); <br/>    }); <br/>})();</pre></code> <br/>paths就是注册自定义包的位置。这里cory包和最外层的dojo文件夹并列。 <br/>然后在cory包中,一共新建4个类,Server.js、UrlParser.js、Router.js、Page.js。 <br/>cory.Server:用于创建http服务器。 <br/>cory.UrlParser:用于解析URL。 <br/>cory.Router:将解析好URL中的pathname进行路由。 <br/>cory.Page:对应相应的URL做出逻辑处理。 <br/>下面就把各个类的代码展示给大家,主要是展示其语法,至于逻辑的话,nodebeginner.org有详细介绍。 <br/> <br/>cory.Server: <br/><pre><code>define([ <br/>    “…/dojo/_base/kernel”, <br/>    “…/dojo/_base/declare”, <br/>    “…/dojo/Stateful” <br/>], function(dojo, declare, Stateful) { <br/>    // summary: <br/>    //  This server to listen the port which you setted. <br/>    return declare(“cory.Server”, Stateful, { <br/>        // default value <br/>        port: 8888, <br/>        _http: dojo.http, <br/>        postscript: function(args) { <br/>            this.inherited(arguments); <br/>            if (args && args.port) { <br/>                this.set(“port”, args.port); <br/>            } <br/>        }, <br/>        start: function(/Function?/callback) { <br/>            console.debug(“Server is starting…”); <br/>            var _port = this.get(“port”); <br/>            this._http.createServer(function(request, response) { <br/>                callback(request, response); <br/>            }).listen(_port); <br/>            console.debug(“Server has started. The port is " + _port + “.”); <br/>        } <br/>    }); <br/>});</pre></code> <br/> <br/>cory.UrlParser: <br/><pre><code>define([”…/dojo/_base/declare"], function(declare) { <br/>    return declare(“cory.UrlParser”, null, { <br/>        parse2Pathname: function(/String/url) { <br/>            var pathname = dojo.url.parse(url).pathname; <br/>            console.debug(“The current path name is: “” + pathname + “”.”); <br/>            return pathname; <br/>        } <br/>    }); <br/>}); <br/></pre></code> <br/> <br/>cory.Router: <br/><pre><code>define(["…/dojo/_base/declare", “…/dojo/Stateful”], function(declare, Stateful) { <br/>    return declare(“cory.Router”, Stateful, { <br/>        request: null, <br/>        response: null, <br/>        //根据不同的url地址名称,路由到不同的页面逻辑处理。 <br/>        //返回是否路由成功。 <br/>        rout: function(/Object/path, /String/pathname) { <br/>            console.debug(“About to route a request for " + pathname); <br/>            var _classAndFunc = path[pathname]; <br/>            var res = this.get(“response”); <br/>            if (!_classAndFunc) { <br/>                console.debug(“But this path was not found.”); <br/>                if (res) { <br/>                    res.writeHead(200, {“Content-Type”: “text/plain”}); <br/>                    res.write(“404 Not found”); <br/>                    res.end(); <br/>                } <br/>            } <br/>            var _lastIndex = _classAndFunc.lastIndexOf(”."); <br/>            var _className = _classAndFunc.substring(0, _lastIndex); <br/>            var _funcName = _classAndFunc.substring(_lastIndex + 1); <br/>            var _page = new dojo.getObject(_className)(); <br/>            _page.set(“request”, this.get(“request”)); <br/>            _page.set(“response”, res); <br/>            _page_funcName; <br/>        } <br/>    }); <br/>}); <br/></pre></code> <br/> <br/>cory.Page: <br/><pre><code>define(["…/dojo/_base/declare", “…/dojo/Stateful”], function(declare, Stateful) { <br/>    return declare(“cory.Page”, Stateful, { <br/>        request: null, <br/>        response: null, <br/>        //@Page(path=["/", “/index”]) <br/>        displayIndex: function() { <br/>            console.debug("“cory.Page.displayIndex” was called"); <br/>            var res = this.get(“response”); <br/>            if (res) { <br/>                var body = <br/>                ‘<html>’+ <br/>                    ‘<head>’+ <br/>                        ‘<meta http-equiv=“Content-Type” content=“text/html; '+ <br/>                        'charset=UTF-8” />’+ <br/>                    ‘</head>’+ <br/>                    ‘<body>’+ <br/>                        ‘<form action="/upload" method=“post” enctype=“multipart/form-data”>’+ <br/>                            ‘<input type=“file” name=“upload” />’+ <br/>                            ‘<input type=“submit” value=“Upload file” />’+ <br/>                        ‘</form>’+ <br/>                    ‘</body>’+ <br/>                ‘</html>’; <br/>                res.writeHead(200, {“Content-Type”: “text/html”}); <br/>                res.write(body); <br/>                res.end(); <br/>            } <br/>        }, <br/>        //@Page(path=["/upload"]) <br/>        upload: function() { <br/>            console.debug("“cory.Page.upload” was called"); <br/>            var req = this.get(“request”), <br/>                res = this.get(“response”); <br/>            if (req && res) { <br/>                var form = new dojo.formidable.IncomingForm(); <br/>                console.debug(“about to parse”); <br/>                form.parse(req, function(error, fields, files) { <br/>                    console.debug(“parsing done.”); <br/>                    dojo.fs.renameSync(files.upload.path, “C:\Documents and Settings\Cory\Local Settings\Temp\test.png”); <br/>                    res.writeHead(200, {“Content-Type”: “text/html”}); <br/>                    res.write(“received image:”); <br/>                    res.write("<img src=’/show’ />"); <br/>                    res.end(); <br/>                }); <br/>            } <br/>        }, <br/>        //@Page(path=["/show"]) <br/>        show: function() { <br/>            console.debug("“cory.Page.show” was called"); <br/>            var res = this.get(“response”); <br/>            if (res) { <br/>                dojo.fs.readFile(“C:\Documents and Settings\Cory\Local Settings\Temp\test.png”, “binary”, function(error, file){ <br/>                    if (error) { <br/>                        res.writeHead(500, {“Content-Type”: “text/plain”}); <br/>                        res.write(error + “\n”); <br/>                    } else { <br/>                        res.writeHead(200, {“Content-Type”: “image/x-png”}); <br/>                        res.write(file, “binary”); <br/>                    } <br/>                    res.end(); <br/>                }) <br/>            } <br/>        } <br/>    }); <br/>}); <br/></pre></code> <br/> <br/> Main.js也需要一点小改动: <br/><pre><code>(function() { <br/>    this.dojoConfig = { <br/>        has: { <br/>            “host-node”: 1 <br/>        }, <br/>        paths: { <br/>            cory: “…/…/cory” <br/>        } <br/>    }; <br/>    require(“H:/Project/dojo_nodejs/dojo/dojo/dojo”); <br/>    var d = dojo; <br/>    [“http”, “url”, “fs”, “formidable”].forEach(function(requiredName) { <br/>        d[requiredName] = require(requiredName); <br/>    }); <br/>    define(“Main”, [ <br/>        “dojo/_base/kernel”, <br/>        “cory/Server”, <br/>        “cory/UrlParser”, <br/>        “cory/Router”, <br/>        “cory/Page” <br/>    ], function(dojo, Server, UrlParser, Router) { <br/>        //这里将地址和类中的方法进行绑定。 <br/>        //其中cory.Page是页面类,后面的.displayIndex、.upload、.show都是该类的方法。 <br/>        var pathMap = { <br/>            “/”: “cory.Page.displayIndex”, <br/>            “/index”: “cory.Page.displayIndex”, <br/>            “/upload”: “cory.Page.upload”, <br/>            “/show”: “cory.Page.show” <br/>        }; <br/>        var server = new Server(); <br/>        server.set(“port”, 8888); <br/>        server.start(function(request, response) { <br/>            var router = new Router(); <br/>            router.set(“request”, request); <br/>            router.set(“response”, response); <br/>            router.rout(pathMap, new UrlParser().parse2Pathname(request.url)); <br/>        }); <br/>    }); <br/>})();</pre></code> <br/> <br/>运行效果: <br/><img class=“aligncenter” src=“http://www.dojocn.org/data/attachment/forum/201112/18/141855ff5bbzqjb477y2q7.jpg” alt=“文件上传” /> <br/> <br/><img class=“aligncenter” src=“http://www.dojocn.org/data/attachment/forum/201112/18/141857rf57rovpptrpv5tc.jpg” alt=“上传成功并显示图片” /> <br/> <br/>后台控制台运行效果: <br/><img class=“aligncenter” src=“http://www.dojocn.org/data/attachment/forum/201112/18/14185923tqicihte0f03e8.jpg” alt=“控制台输出” /> <br/>怎么样,这样的面向对象的方式,让思路更清晰,要比nodebeginner上的例子,引用传来传去的清晰多了吧。 <br/> <br/>后记:如果采用dojo来开发node.js后台程序,那么,可以继续封装成,类似于servlet形式,甚至可以进行json配置等。这样更有利于学习成本的降低,减少开发大型后台的人力、时间成本等。

2 回复

这里用到的define方法是什么啊?

觉得还是不要让 dojo 框架染指 node,,哪怕基础库也没必要……

回到顶部