2015年1月

Node.js利用回调实现异步编程

回调是一个函数,它被当做参数传给异步函数,它描述异步操作完成后要做什么
在这里我们搭建一个简单的HTTP服务器,让它实现如下功能:

  • 异步获取存放在JSON文件中的文章的标题
  • 异步获取简单的HTML模板
  • 把标题组装到HTML页面里
  • 把HTML页面发送给用户

JSON文件会被格式化成一个包含文章标题的字符串数组,列表内容如下所示

titles.json

[
    "Hello World",
    "Miss Home",
    "Bye HDU"
]

用来渲染页面的HTML模板

template.html

<!Doctype html>
<html>
<head>
</head>
<body>
    <h1>Latest Posts</h1>
    <ul><li>%</li></ul> // 利用replace()函数,%将会在之后被小标题内容所替换
</body>
</html>

使用回调函数的实例

recent.js

var http = require('http');
var fs = require('fs');

var server = http.createServer(function(req,res){
    getTitles(res);
}).listen(8080,"127.0.0.1");

function getTitles(res){
    fs.readFile('./titles.json',function(err,data){
        if(err) return hadError(err,res)
        getTemplate(JSON.parse(data.toString()),res) //若未发生错误,异步调用getTemplate()函数
    })
}

function getTemplate(titles,res){
    fs.readFile('./template.html',function(err,data){
        if(err) return hadError(err,res)
        formatHtml(titles,data.toString(),res) //若未发生错误,异步调用formatHtml()函数
    })
}

function formatHtml(titles,tmpl,res){
    var html = tmpl.replace('%',titles.join('</li><li>'));
    res.writeHead(200,{'Content-Type':'text/html'});
    res.end(html);
}

function hadError(err,res){ // 若过程中出现了错误,函数将把错误输出至控制台,同时返回客户端'Server Error'
    console.error(err)
    res.end('Server Error')
}

结果如图所示
1.png

Node中的大多数内置模块在使用回调时都会带两个参数
第一个是用来放可能会发生的错误的,通常简写为err或er,第二个参数用来存放结果

Read More »

Node.js模块化编程

ABOUT NAMESPACE COLLISIONS

Node的模块系统避免了对全局作用域的污染,也就避免了命名空间的冲突

如果在PHP中有如下的代码

function uppercase_trim($text) {
    return trim(strtoupper($text));
}
include('string_handlers.php');

假如在string_handlers.php文件中也定义了一个 uppercase_trim 函数

那么程序将报错 Fatal error: Cannot redeclare uppercase_trim()

在PHP中可以用命名空间避免这个问题,可在NODE中,是不让你有机会在不经意间污染全局命名空间

Node模块允许你从被引入文件中选择要暴露给程序的函数和变量,如果模块返回的函数或变量不止一个,那它可以通过设定exports对象的属性来指明,但如果模块只返回一个函数或变量,则可以设定module.exports属性

Node的模块系统避免了对全局作用域的污染,从而也就避免了命名冲突,并简化了代码重用

CREATE A MODULE

模块可以是一个文件,也可以是包含一个或多个文件的目录,若是一个目录,Node通常会在这个目录下找index.js作为模块的入口,这个默认设置是可以重写的

典型的模块是一个包含exports对象属性定义的文件,这些属性可以使任意类型的数据,比如字符串、对象和函数

下面演示利用Node的模块,编程演示货币转换,软妹币-美元

currency.js

var rmbdollar = 0.1603;
function roundTwoDecimals(amount) {
    return Math.round(amount*100)/100;
}
exports.rmbToUS = function(rmb){
    return roundTwoDecimals(rmb*rmbdollar);
}
exports.USTormb = function(us){
    return roundTwoDecimals(us/rmbdollar);
}

笔者在写这篇博客时,1 RMB = 0.1603 Dollar

函数roundTwoDecimals()的作用是保留小数位四舍五入后的两位小数

这里exports对象只设定了两个属性,也就是说引入这个模块的代码只能访问到rmbToUS和USTormb这两个函数

变量rmbdollar作为私有变量仅作用与这两个函数的逻辑内部,程序是不能直接访问它的

usecurrency.js

var currency = require('./currency'); //在引入时,.js扩展名可忽略
console.log('5288 RMB equals this amount of US dollars = '+currency.rmbToUS(5288)+' dollars');
console.log('649 US dollars equals this amount of RMB = '+currency.USTormb(649)+' yuan');

在Node定位到并计算好逆的模块之后,require函数会返回这个模块中定义的exports对象中的内容,这里是两个货币转换的函数,然后我们就可以直接调用它们进行货币转换

打开Command 输入 node usecurrency

2.png

组装模块中的exports对象是在单独文件中组织可重用代码的一种简便的方法

Read More »

初识Node.js

WHAT IS NODE.JS

官网上(http://www.nodejs.org)给Node下的定义是: "一个搭建在Chrome JavaScript运行时上的平台,用于构建高速、可伸缩的网络程序。Node.js采用的事件驱动、非阻塞I/O模型,使它轻量又高效,并成为构建运行在分布式设备上的数据密集型实时程序的完美选择。"

Node.js® is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

NODE.JS INSTALL

Node的安装非常简单,只需到官网上下载对应的系统安装即可

国际惯例,先来一句 Hello world

Hello.js

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8080, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8080/');

打开Command 输入 node hello

node.png

返回服务器已成功运行在本机的8080端口上了

该例中所创建的并不是一个功能全面的HTTP服务器,它并不能处理任何HTML文件、图片,无论请求什么

它都将返回“Hello World”

在浏览器中输入 127.0.0.1:8080 ,你将看见该文本。

1.png

此时Node.js应用并没有退出

这是因为创建了一个服务器,Node.js应用将继续运行,并响应请求,直到你关闭它

Read More »

深入理解 HTTP POST & GET Request

Reference RFC 2616

在 HTTP/1.1 协议中共定义了8种Request Method

  • OPTIONS
    返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。

  • HEAD
    向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。

  • GET
    向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。

  • POST
    向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。

  • PUT
    向指定资源位置上传其最新内容。

  • DELETE
    请求服务器删除Request-URI所标识的资源。

  • TRACE
    回显服务器收到的请求,主要用于测试或诊断。

  • CONNECT
    HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

The return code of the response always notifies the client whether a method is currently allowed on a resource, since the set of allowed methods can change dynamically.
An origin server SHOULD return the status code 405 (Method Not Allowed) if the method is known by the origin server but not allowed for the requested resource;and 501 (Not Implemented) if the method is unrecognized or not implemented by the origin server
当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Method Not Allowed);当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码501(Not Implemented)

一般在 Web Application 中,比较常用的就是GET和POST这两种Request方式了,接下来深入讨论这两种方式的区别

Read More »