代码改变世界

nodejs入门篇

2013-10-11 22:03  king0222  阅读(462)  评论(0编辑  收藏  举报

nodeJs入门篇

nodeJs对于前端开发工程师们来说是个福音,我们可以用自己最熟悉的语言来开发后台了,好爽啊,爽歪歪啊。

入门吧, 从简单开始:

nodejs官网中给了我们详细的API文档作为参考,里面的每一个模块都解释的非常清晰,包括他提供在主页的例子,可以作为我们入门的第一个材料。

nodejs中我们第一个先熟悉的模块就是http模块,我们用这个模块可以快速搭建一个服务器出来。

1 var http = require('http');
2 
3 http.createServer(function(req, res){
4   res.writeHead(200, {'Content-Type': 'text/html'});
5   res.end('hello world');
6 }).listen(8080, function(){
7   console.log('server listening on 8080');
8 })

通过这一段简单的代码,我们就可以快速的搭建了一个简单的服务器,在终端运行该代码:node test.js后,我们能看到终端输出了'server listening on 8080'。

打开浏览器,地址栏中输入'localhost:8080',回车后我们能看到页面输出显示'hello world'.

接下来,我们想要根据路由来访问不同信息。我们可以先自定义出一些简单的文本作为路由输出。

var pages = [
    {id: '1', route: '', output: 'hello world!'},
    {id: '2', route: 'about', output: 'a page about your home!'},
    {id: '3',route: 'another page', output: function(){return 'hree\'s' + this.route;}}
];

将这段代码放在创建服务器之前,也就是http.createServer之前,接下来,我们只需要在createServer的回调函数中,根据访问路径来循环pages就可以了。

http.createServer(function(req, res){
    console.log('request url is:', req.url);
    var lookup = path.basename(decodeURI(req.url));
    pages.forEach(function(page){
        if (page.route === lookup) {
          res.writeHead(200, {'Content-Type':'text/html'});
          res.end(typeof page.output === 'function' 
       ? page.output() : page.output);
        }
    });
    res.writeHead(404);
    res.end('page not found');
}).listen(8080);

我们可以在浏览器中访问'localhost:8080','losthost:8080/about'或其他的url来测试代码结果。

这段简单的代码能给我们一个路由最基本的概念,在这里我们可以慢慢对他进行升级再造。

上面的代码中,我们用到了path模块(var lookup = path.basename(decodeURI(req.url));),因此,需要在顶部引入该模块var path = require('path');

在处理服务器的地址问题上,path, url, querystring这几个模块我们可能会经常用到,另外这几个模块所提供的方法并不多,记起来比较容易。

为了尝试一下url模块的使用,我们可以在现在代码的基础上再做修改,将路由访问方式改为'localhost:8080?id=xx'的形式,这就需要我们将Url中的查询条件部分分离出来,也就是id=xx部分。

为了得到查询条件的值,我们通过url.parse(req.url)方法将访问地址转化为一个对象,详细的用法我们应该多参考官方文档。

通过var id = url.parse(decodeURI(req.url), true).query.id;我们即可得到查询的id.现在的代码可以修改为

var http = require('http');
var path = require('path')
var url = require('url');

http.createServer(function(req, res){
    console.log('request url is:', req.url);
    var lookup = path.basename(decodeURI(req.url));
    var id = url.parse(decodeURI(req.url), true).query.id;
    if (id) {
        pages.forEach(function(page){
            if (page.id == id) {
              res.writeHead(200, {'Content-Type':'text/html'});
              res.end(typeof page.output === 'function' 
                 ? page.output() : page.output);
            }
        });
    }
    res.writeHead(404);
    res.end('page not found');
}).listen(8080);

到现在为止,我们所做的东西,都没有任何实际用途,作为一个服务器最起码的功能,我们应该能够访问静态文件。

要访问文件,我们就需要用到fs模块,这个模块提供了很多的方法给我们读写文件,我们先从exists,readFile这两个方法开始去了解fs模块。

要判断文件是否存在,nodejs为我们提供了fs.exists(f, function(exists){})接口来访问,读取文件有fs.readFile(f, function(err, data){}).接口的设计模式给我们没有任何的违和感,熟悉到爆的脚本编写方式让我们很容易就接受了nodejs.

http.createServer(function(req, res){
    console.log('server url is:', req.url);
    var lookup = path.basename(decodeURI(req.url));

    //content/目录为静态文件存放的位置
    var f = 'content/' + lookup;
    var id = url.parse(decodeURI(req.url), true).query.id;
    fs.exists(f, function(exists){
        if (!exists){
            res.writeHead(404, {'Content-Type': 'text/html'});
            res.end('file not exists');
        } 
        fs.readFile(f, function(err, data){
            if (err) {
                res.end('file read wrong');
            }
            res.end(data);
        });
    });
}).listen(8080, function(){
    console.log('server lister on 8080');
});

浏览器访问'localhost:8080/content/xxx.html‘ 我们就可以浏览到xxx.html这个页面了(前提是content目录下有这个文件,否则页面显示file not exists.

对于入门来说,看懂官方文档是相当快速的一种方式,对于http.createServer(function(req,res){})这个东西来说,文档告诉了我们回调中包含了请求对象(req)和响应对象(res)。接下来,我们如何知道req或者res中到底包含哪些方法或者属性呢,在官方文档中,我们点击http.createServer([requestListener])这个连接后即可跳到他的详细介绍的位置,在那里有这样一段代码:

Emitted each time there is a request. Note that there may be multiple requests per connection (in the case of keep-alive connections). request is an instance of http.IncomingMessage and response is an instance ofhttp.ServerResponse

这段原文描述告诉我们req是http.IncomingMessage的一个实例,同理,res是http.serverResponse的一个实例,所以我们需要查http.IncomingMessage的详细描述。在跳到http.IncomingMessage那里后我们能很快看到他所提供的所有的属性和方法,包括(message.url, message.headers, message.method等),对应的就是(req.url, req.headers,  req.method等).学习一门语言,是需要经过不断努力,不断重复的吧。