what it is?
- Node.js的本质是一个Javascript的解析器
- Node.js是Javascript 的运行环境
- Node.js是一个服务器程序
- Node.js本身使用的是V8引擎
- Node不是web服务器
Why use it?
- 为了提供高性能的web服务
- IO性能强大
- 事件处理机制完善
- 天然能够处理DOM
- 社区非常活跃,生态圈日趋完善
The advantage
- 处理大流量数据
- 适合实时交互的应用
- 完美支持对象数据库
- 异步处理大量并发链接
安装cnpm
- npm install cnpm 安装cnpm
第一个node程序
- 创建 hello.js 并编辑 console.log("helloworld")
- node hello.js //运行
#node最简单的web服务
-
创建 server.js
-
引入 原生 api
var http = require('htttp');
- 创建一个服务
http.createServer(function (request,response) {
//定义HTTP头
response.writeHead(200, {'Content-Type':'text/plan'});
//发送相应的数据
response.end('Hello world!\n');
}).listen(8000);
//服务运行之后输出一行信息
console.log('server is running...');
- 运行
node server.js
- 打开浏览器 127.0.0.1:8000
Nodejs 环境及npm命令的深入
REPL
全称交互式解释器 敲 node 命令进入 可以在环境之后 直接进行代码 的编写 运算 优点类似 浏览器的 console控制台 一般来说我们可以在此环境下 进行一些 简单的 代码运算 验证
- ctrl + c -退出当前终端
- ctrl + c -按下两次 退出 Node REPL
- ctrl + d -退出Node REPL (linux环境下)
- 向上/向下 键 -查看输入的历史命令
- tab键 -列出当前命令
- .help -列出使用命令
- .break -退出多行表达式
- .clear -退出多行表达式
- .save filename -保存当前的Node REPL 会话到指定文件
- .load filename -载入当前 Node REPL 会话的文件内容。
npm包管理器
- npm install npm -g //升级npm
- npm install express -g//安装包express
- npm uninstall packagename // 卸载包
- npm search packagename // 查找包
- npm help
- npm help install // 具体查看 某个命令
- cnpm 与 npm 的使用方法本质是相同的 只是服务器不同 一个国内 一个国外
什么是回调
- 函数调用方式分为三类 :同步调用、回调和异步调用。
- 回调时一种双向调用模式
- 可以通过回调函数来实现回调
阻塞与非阻塞
- 阻塞和非阻塞关注的是程序在等待调用的结果(消息,返回值)时的状态。
- 阻塞就是做不完不准回来
- 非阻塞就是你先做,我现在看看有其他事没有,做完了告诉我一声
//阻塞时代码
var fs = require('fs');
var data = fs.readFileSync('data.txt'); // 阻塞时用 同步读取 readFileSync 非阻塞时用 readFile
console,log(data.toString());
//非阻塞代码
var fs = require('fs');
fs.readFile('filename.txt',function(err,data){
// todo something
if(err){
return console.error(err)
}
console.log(data.toString());
})
cosnole.log("程序执行完毕")
Node.js事件驱动机制
事件驱动模型
事件与事件绑定
- nodejs 是一个单进程 单线程的程序,它并不能同时并发完成更多的事情,只能通过事件或者回调来实现并发效果
- nodejs 的 api 全都是异步执行的,而且都是作为独立的线程处理的
- nodejs 中的 几乎所有的事件 都是依据观察者模式 来实现的 观察者模式 是设计模式中的一种
- EventEmitters 对象 产生 Events 实例
事件处理代码
//1. 引入 events对象,创建 eventEmitter对象
var events = require('events');
var eventEmitter = new events.EventEmmitter();
//2. 绑定事件处理程序
var connctHandler = function connected(){
console.log('connected被调用了');
};
eventEmitter.on('connection', connctHandler()); //完成事件绑定
//3.触发事件
eventEmitter.emit('connection');
console.log("程序执行完毕");
Nodejs 模块化
模块化的概念和意义
- 为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统
- 模块是Node.js应用程序的基本组成部分
- 文件和模块是一一对应的。一个Node.js文件就是一个模块
- 这个文件可能是Javascript代码、JSON或者编译过的C/C++扩展
- Node.js中存在4类模块(原生模块和3种文件模块)
Node.js中的模块
Node.js的模块加载流程
文件的缓存区 有文件模块缓存区 和 原生模块缓存区
- require 方法接受一下几种参数的传递: 1 http、fs、path等,原生模块 2 ./mod或../mod,相对路径的文件模块 3 /pathtomodule/mo,绝对路径的文件模块
- mod,非原生模块的文件模块
模块化代码案例
//main.js 主要调用模块的文件
var Hello = require('./hello');
hello = new Hello();
hello.setName('Richard');
hello.sayHello();
//hello.js 模块文件
function Hello(){
var name ;
this.setName = function(argName){
name = argName
}
this.sayHello = function(){
console.log('hellko' + name);
}
}
module.exports = Hello;
函数
- 在javascript 中,一个函数可以作为另一个函数的参数。
- 我们可以先定义一个函数,然后传递,也可以在传递参数的地方直接定义函数。
- Nodejs 中的函数使用与Javascript 类似
代码示例:
function say(word){
console.log(word);
}
function execute(someFunction,value){
someFunction(value);
}
execute(say,'hello')
匿名函数
function execute(someFunction,value){
someFunction(value)
}
execute(function(word){
console.log(word)
},'hello');
示例Ⅱ 同样的功能,不同的实现方式
//匿名函数
var http = require('http');
http.createServer(function(request,response){
response.writeHead(200,{"Content-Type":'text/plain'});
response.write("Hello world");
response.end();
}).listen(8000)
//先定义后传递
var http = require("http");
function onResquest(request,reponse){
response.writeHead(200,{"Content-Type":'text/plain'});
response.write("Hello World");
response.end();
}
http.createServer(onResquest).listen(8888);
路由
我们所需要的所有数据都会包含在request对象中,该对象作为onRequest()回调函数的第一个参数传递。但是为了解析这些数据,我们需要额外的Node.JS模块,他们分别是url 和querystring模块
例如我们 访问 http://localhost:8888/start?foo=bar&hello=world
url.parse(string).query
|
url.parse(string).pathname |
| |
| |
------ -------------------
http://localhost:8888/start?foo=bar&hello=world
--- -----
| |
| |
querystring.parse(queryString)["foo"] |
|
querystring.parse(queryString)["hello"]
//server.js
var http = require("http");
var url = require("url");
function start(route) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
//console.log("Request for " + pathname + " received.");
route(pathname,response);
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
//router.js
function route(pathname,response) {
if(pathname == '/'){
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}else if(pathname == "/index/home"){
response.end('index');
}else{
response.end('index');
}
}
exports.route = route;
//app.js
var server = require("./server");
var router = require("./router");
server.start(router.route);
获取GET请求内容
var http = require('http');
var url = require('url');
var util = require('util'); //帮助类
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
res.end(util.inspect(url.parse(req.url, true)));
}).listen(3000);
获取POST请求内容
var http = require('http');
var querystring = require('querystring');
var util = require('util');
http.createServer(function(req, res){
// 定义了一个post变量,用于暂存请求体的信息
var post = '';
// 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
req.on('data', function(chunk){
post += chunk;
});
// 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
req.on('end', function(){
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(3000);
全局对象与全局变量
global 就是nodejs的全局对象 类比javascript的window
-
__filename __filename 表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是模块文件的路径。
-
__dirname __dirname 表示当前执行脚本所在的目录。
-
setTimeout(cb, ms) setTimeout(cb, ms) 全局函数在指定的毫秒(ms)数后执行指定函数(cb)。:setTimeout() 只执行一次指定函数。返回一个代表定时器的句柄值。
-
clearTimeout(t) clearTimeout( t ) 全局函数用于停止一个之前通过 setTimeout() 创建的定时器。 参数 t 是通过 setTimeout() 函数创建的定时器。
-
setInterval(cb, ms) setInterval(cb, ms) 全局函数在指定的毫秒(ms)数后执行指定函数(cb)。返回一个代表定时器的句柄值。可以使用 clearInterval(t) 函数来清除定时器。setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
-
process process 是一个全局变量,即 global 对象的属性。它用于描述当前Node.js 进程状态的对象,提供了一个与操作系统的简单接口。通常在你写本地命令行程序的时候,少不了要 和它打交道。下面将会介绍 process 对象的一些最常用的成员方法。
工具util
underscore.js
文件系统
读取文件
var fs = require("fs");
// 异步读取
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("异步读取: " + data.toString());
});
// 同步读取
var data = fs.readFileSync('input.txt');
console.log("同步读取: " + data.toString());
console.log("程序执行完毕。");
打开文件
fs.open(path, flags[, mode], callback) 参数说明:
- path - 文件的路径。
- flags - 文件打开的行为。
- mode - 设置文件模式(权限),文件创建默认权限为 0666(可读,可写)。
- callback - 回调函数,带有两个参数如:callback(err, fd)。
获取文件信息
fs.stat(path, callback) 参数说明
- path - 文件路径。
- callback - 回调函数,带有两个参数如:(err, stats), stats 是 fs.Stats 对象。
写入文件
fs.writeFile(file, data[, options], callback)
- file - 文件名或文件描述符。
- data - 要写入文件的数据,可以是 String(字符串) 或 Buffer(缓冲) 对象。
- options - 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8, 模式为 0666 , flag 为 'w'
- callback - 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。
var fs = require("fs");
console.log("准备写入文件");
fs.writeFile('input.txt', '我是通 过fs.writeFile 写入文件的内容', function(err) {
if (err) {
return console.error(err);
}
console.log("数据写入成功!");
console.log("--------我是分割线-------------")
console.log("读取写入的数据!");
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("异步读取文件数据: " + data.toString());
});
});
等等 方法 参考 菜鸟教程