服务端JavaScript
众所周知的,JavaScript是运行在浏览器的脚本语言,JavaScript通常作为客户端程序设计语言使用,以JavaScript写出的程序常在用户的浏览器上运行。直至Nodejs的出现,Node.js大部分基本模块都用JavaScript语言编写,Node.js的出现使JavaScript也能用于服务器端编程。Node.js含有一系列内置模块,使得程序可以脱离Apache HTTP Server或IIS,作为独立服务器运行。
Node.js概况
Node.js允许通过JavaScript和一系列模块来编写服务器端应用和网络相关的应用。
核心模块包括文件系统I/O、网络(HTTP、TCP、UDP、DNS、TLS/SSL等)、二进制数据流、加密算法、数据流等等。
运用Node.js的相关框架可以快速的完成应用的开发,常用的框架有Express.js、Koa.js、Socket.IO和Connect等。
Node.js主要用于编写像Web服务器一样的网络应用,这和PHP和Python是类似的。但是Node.js与其他语言最大的不同之处在于,PHP等语言是阻塞的(只有前一条命令执行完毕才会执行后面的命令),而Node.js是非阻塞的(多条命令可以同时被运行,通过回调函数得知命令已结束运行)。
Node.js是事件驱动的。开发者可以在不使用线程的情况下开发出一个能够承载高并发的服务器。
Node.js使用Google V8JavaScript 引擎,因为V8是基于BSD许可证的开源软件且速度非常快并且专注于网络功能,在HTTP、DNS、TCP等方面更加成熟。
Node.js的包管理器npm可完成相关依赖包的模块下载。
Node.js简单应用
应用说明:通过启动本地服务器,完成图片上传并展示的功能。
一、需要的模块
HTTP服务器模块(HTTP服务器):http://nodejs.cn/api/http.html#http_http
fs模块(文件系统):http://nodejs.cn/api/fs.html#fs_file_system
url模块(网址):http://nodejs.cn/api/url.html#url_class_url
formidable模块(处理文件上传,ps:该模块需要npm install安装):https://cnodejs.org/topic/4f16442ccae1f4aa2700104d
二、思路分析
1.启动服务器,发送HTTP请求
2.通过获取请求参数,执行路由跳转或处理程序
三、模块抽取及代码展示
1.抽取出主页面index.js(解耦)
/** * Created by aaron. */ var server=require('./server'); var router=require('./router'); var requestHandlers=require('./requestHandlers') var handle={} handle['/']=requestHandlers.start, handle['/start']=requestHandlers.start, handle['/upload']=requestHandlers.upload, handle['/show']=requestHandlers.show; server.start(router.route,handle);
2.创建服务器并监听客户端请求事件server.js
/** * Created by aaron. */ var http=require('http'); var url=require('url'); function start(route,handle) { function onRequest(request,response) { var postData=''; var pathname=url.parse(request.url).pathname; console.log('Request for'+pathname+'received'); //node-formidable会对postData及setEncoding处理 /*request.setEncoding('utf8'); request.addListener('data',function (postDataChunk) { postData+=postDataChunk; console.log('Received POST data chunk'+postDataChunk+'.'); }); request.addListener('end',function () { route(handle,pathname,response,postData); })*/ route(handle,pathname,response,request); } http.createServer(onRequest).listen(8888); console.log('Server has started.'); } exports.start=start;
3.获取请求参数并执行路由跳转router.js
/** * Created by aaron. */ function route(handle,pathname,response,request) { console.log('About to route a request for'+pathname); if(typeof handle[pathname]==='function'){ handle[pathname](response,request); }else{ console.log('No request handler found for'+pathname); response.writeHead(404,{'Content-type':'text/plain'}); response.write('404 Not found'); response.end(); } } exports.route=route;
4.请求处理程序并作出响应requestHandler.js
/** * Created by aaron. */ //执行非阻塞操作,从node来执行一个shell命令 var exec=require('child_process').exec; var querystring=require('querystring'); var fs=require('fs'); var formidable=require('formidable'); function start(response) { console.log('Request handler "start" was called.'); var body='<html>' + '<head>' + '<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>' + '</head>' + '<body>' + '<form action="/upload" method="post" enctype="multipart/form-data">' + '<input type="file" name="upload"/>' + '<br/>'+ '<input type="submit" value="Upload file"/>'+ '</form>' + '</body>'+ '</html>'; response.writeHead(200,{'Content-type':'text/html'}); response.write(body); response.end(); } function upload(response,request) { console.log('Request handler "upload " was called.'); var form=new formidable.IncomingForm(); form.parse(request,function (error,fields,files) { console.log('parsing done:<br/>'+files.upload.path); fs.renameSync(files.upload.path,'C:/temp/test.jpg'); response.writeHead(200,{'Content-type':'text/html'}); response.write('received image:<br/>'); response.write('<img src="/show"/>'); response.end(); }) /*response.writeHead(200,{'Content-type':'text/plain'}); response.write('You`ve sent the text:'+ querystring.parse(postData).text ); response.end();*/ } function show(response,postData) { console.log('Request handler "show" was called.'); fs.readFile('C:/temp/test.jpg','binary',function (error,file) { if(error){ response.writeHead(500,{'Content-type':'text/plain'}); response.write(error+' '); response.end(); }else{ response.writeHead(200,{'Content-type':'image/jpg'}); response.write(file,'binary'); response.end(); } }) } exports.start=start; exports.upload=upload; exports.show=show;
5.结果展示
选择图片--> 上传 --> 展示图片
补充说明
fs.renameSync()执行函数时如果执行图片上传的盘不是系统盘时会提示报错,解决方案是图片路径设置为绝对路径并设置为系统盘。
更多参考
GitHub源码:https://github.com/PCAaron/node
《Node.js入门》:https://www.nodebeginner.org/index-zh-cn.html
维基百科:https://zh.wikipedia.org/wiki/Node.js
Node.js中文网:http://nodejs.cn/api/