四个例子入门NodeJS

  • 目录
    {:toc #meuid}

0.前言

NodeJS是什么?

JavaScript是一种运行在浏览器的脚本,它简单,轻巧,易于编辑,这种脚本通常用于浏览器的前端编程,但是一位开发者Ryan有一天发现这种前端式的脚本语言可以运行在服务器上的时候,一场席卷全球的风暴就开始了。

Node.js是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行的数据密集型的实时应用。

Node是一个Javascript运行环境(runtime)。实际上它是对Google V8引擎进行了封装。V8引 擎执行Javascript的速度非常快,性能非常好。Node对一些特殊用例进行了优化,提供了替代的API,使得V8在非浏览器环境下运行得更好。

我们该如何入门学习?

对于一个新的技术来说,入门学习很重要,如果有一个好的入门学习资料,将会对以后深入学习该技术产生很大的帮助,本文就是以这中思想来解说的,希望能够对学习NodeJS的人来说有一个好的开始,也欢迎大家对本文指出不足。

本文源码

关于如何安装NodeJS,对于Linux上用户直接到官网下载编译过的安装包,然后加入到环境变量中即可

ln -s /home/software/node-v0.12.7-linux-x64/bin/node /usr/local/bin/node
ln -s /home/software/node-v0.12.7-linux-x64/bin/npm /usr/local/bin/npm

输入node回车即可进入node命令。

1.了解结构

入口

var server=require("./server");
server.start();

NodeJS入口是指node命令后面要执行的文件,例如”node helloworld.js”即可之执行编写的代码,其中require是之加载模块,这里加载了本地的一个模块,也可加载内置的模块,比如require(“http”),是指加载node中自带的http模块,这点和函数式编程有点像。后面就可以调用具体的function了,这点就是Javascript里面的东西了,很简单吧。

server:

function start(){
  function onRequest(request,response){
     router.route(pathname,request,response,null);
   }
  http.createServer(onRequest).listen(8888);
}
exports.start=start;

server.js中的内容就是服务请求的入口了,包含请求的处理,路由的处理。最好是把处理放在一个单独的文件中这样管理起来也很方便。exports就是把该方法暴露出去,可以让外边的程序调用。最后在一个端口上监听就可以了.

route:

function route(pathname,request,response,data){
  handler.menu(request,response,data);
}
exports.route=route;

对于路由后的内容要有一个处理的文件,就是requestHandlers,这个文件中是对每个路由到的地址进行具体的请求。

handler:

function menu(request,response,postdata){}
function start(request,response,postdata){}
function textpost(request,response,postdata){}
function filepost(request,response,postdata){}

exports.menu=menu;
exports.start=start;
exports.textpost=textpost;
exports.filepost=filepost;

每个对应一个请求,这是一种最简单的处理方式。

了解以上的内容后,就可以写一个简单的有结构的程序了,下面的示例是在以上的基础上演示了几种常见的情景:非阻塞请求,post数据,查看图片,上传图片。

2.示例一:阻塞演示

对于处理一个比较费时的操作,如果要在当前线程中处理的话会阻塞,一旦产生阻塞就会影响其它请求的执行,一种处理阻塞的方法时利用回调,将好事耗时的任务利用child_process的操作来执行,也可以将response的方法在数据处理完后发送给客户端。

在requestHandlers.js中start的方法演示了如何处理阻塞请求:

function start(request,response,postdata){
  console.log("request handler 'start' was called.");
  exec("find /",{timeout:10000,maxBuffer:20000*1024},function(error,stdout,stderr){
    response.writeHead(200,{"Content-Type":"text/plain"});
    response.write(stdout);
    response.end();
    });
}

3.示例二:post请求

对于一个请求,如果不带参数的化可以直接路由即可,但对于post方法中带的数据的情况,node 中有专门的方法处理,由于该过程也回产生阻塞,为了使整个过程非阻塞,Node.js会将POST数据拆分成很多小的数据块,然后通过触发特定的事件,将这些小数据块传递给回调函数。这里的特定的事件有data事件(表示新的小数据块到达了)以及end事件(表示所有的数据都已经接收完毕)。

我们需要告诉Node.js当这些事件触发的时候,回调哪些函数。怎么告诉呢? 我们通过在request对象上注册监听器(listener) 来实现。这里的request对象是每次接收到HTTP请求时候,都会把该对象传递给onRequest回调函数。

在server.js中onRequest的方法演示了如何该情况:

request.setEncoding("utf-8");
request.addListener("data",function(postDataChunk){
  postData+=postDataChunk;
  console.log("Received POST data:"+postDataChunk+".");
});
request.addListener("end",function(){
  router.route(pathname,request,response,postData);
});

requestHandlers.js中upload方法就可以拿到数据,然后写回客户端:

response.writeHead(200,{"Content-Type":"text/plain"});
response.write("You've sent : "+querystring.parse(postdata).text);
response.end();

4.示例三:查看图片

对于查看服务器上的资源,可以用file system模块,调用方式如:require(“fs”).
requestHandlers.js中show方法就是读取一个图片的示例:

fs.readFile("/root/图片/new.png","binary",function(error,file){
    if(error){
        response.writeHead(500,{"Content-Type":"text/plain"});
        response.write(error+"\n");
        response.end();
    }else{
        response.writeHead(200,{"Content-Type":"image/png"});
        response.write(file,"binary");
        response.end();
    }
});

在示例中不仅此处用了该方法,加载具体的html文件也用到该模块。

5.示例四:图片上传

文件上传也是一个比较常见的情形,单要用到一个模块formidable,该模块需要自己安装,node默认没有自带.

安装方法:

npm install formidable

requestHandlers.js中uploadfile方法就是处理上传上来的文件的示例:

var form=new formidable.IncomingForm();
    form.parse(request,function(error,fields,files){
        fs.renameSync(files.upload.path,"/root/图片/new.png");
        response.writeHead(200,{"Content-Type":"text/html"});
        response.write("received image:<br/>");
        response.write("<img src='/show' />");
        response.end();
});

注意的是:这里不再调用addListener方法,而是要自己处理上传的资源。
单独的处理,避免和其它处理方式混淆:

if(pathname=="/uploadfile"){
    router.route(pathname,request,response,null);
}else{
    //.....
}

6.总结

通过这几个示例可以更加深入的了解到node的开发方式,希望能对刚入门的人有一个指导性的作用。