NodeJS_01

NodeJS七天公开课_day01_主讲老师:李鹏周

官网: http://nodejs.org/

node.js是一个javasript运行时环境,能执行js代码
node.js中,没有BOM和DOM

1.事件驱动event-driven
2.non-block非阻塞模型
3.轻量-高效


npm  全称是: Node.Package.Manage

构建于chrome’s V8 JavaScript Engine


Node的作用:

用来写1.后台服务器,2.命令行工具(如Webpack)


演示node环境中,并不再有bom和dom了

node_02.js代码如下:

console.log(window);


node_03.js读取同级目录下的anohana.txt文件

代码如下:


// 导入fs模块
var fs = require('fs');
var filePath = 'anohana.txt';
// 如果读取成功,参数1 error 为null
// 如果读取失败,参数1 error 为对象,参数2 data 为undefined
function callbackFunction (error, data) {
	if (error) {
		console.log("文件读取失败\nerror: " + error)
	}else{
		console.log("文件读取成功");
		console.log("data: " + data);
	}
}

var data = "あの日見た花の名前を僕達はまだ知らない";
fs.readFile(filePath, callbackFunction);

读取失败时效果如下:


写入文件的代码如下:

// 导入fs模块
var fs = require('fs');
var filePath = 'anohana.txt';
// 参数:如果写入成功, error为null
// 如果写入失败,error则为对象
function callbackFunction (error) {
	if (error) {
		console.log("文件写入失败\nerror: " + error)
	}else{
		console.log("文件写入成功",false);
		console.log("error: " + error);
	}
}

var data = "あの日見た花の名前を僕達はまだ知らない";
fs.writeFile(filePath, data, callbackFunction);

写入失败时的效果如下: (例如文件名有非法字符)


NodeJS提供简单的http服务,代码如下:

// 导入http模块
var http = require('http');
var server = http.createServer();
function onReciveFuntion (request,response) {
	console.log("收到浏览器请求,路径是:\n" + request.url)	
	// 回写内容
	var responseText = '<html><head><title>beyond心中の动漫神作</title><link rel="icon" href="http://vwhm.net/beyond.jpg" type="image/x-icon"/><meta charset="UTF-8"></head><span style="color:#BB0A1E;">面码</span>:"最喜欢仁太了~';
	response.write(responseText);
	response.end();
}
// 注册事件
server.on("request",onReciveFuntion);

function onLaunchFinishFunction () {
	console.log("服务启动成功",false);
}
// 监听5267端口,启动服务
// localhost:5267
server.listen(5267,onLaunchFinishFunction);

效果如下:


往浏览器中回写的内容 必须是 字符串或二进制,不能是 数字,对象,boolean,否则报错如下:

First argument must be a string or Buffer

初步实现,根据请求路径来返回不同的数据

当请求http://localhost:5267时,返回一段html

当请求http://localhost:5267/girl时,返回一个json对象数组字符串,并解决乱码

当请求http://localhost:5267/favicon.ico时,重定向到另一个url去下载网站图标

代码如下:

// 导入http模块
var http = require('http');
var server = http.createServer();
function onReciveFuntion (request,response) {
	// 所有的url都是以 / 开头
	var url = request.url
	NSLog("收到浏览器请求,路径是:\n" + url)	;
	if(url === '/girl'){
		var girlArr = [
						{girlName:"mathilda",age:12},
						{girlName:"面码",age:15},
						{girlName:"逢坂大河",age:16}
					  ];
	    // 解决乱码
	    response.setHeader('Content-Type','text/html;charset=UTF-8');
	    response.end('<head><title>beyond心中の动漫神作</title></head>' + JSON.stringify(girlArr));

	}else if(url === '/favicon.ico'){
		// 如果请求的是icon图标,则302重定向
		response.writeHead(302, {'Location': 'http://vwhm.net/beyond.jpg'});
		response.end();

	}else{
		// 回写的内容 必须是字符串或二进制,不能是 数字,对象,boolean
		var responseText = '<html><head><title>beyond心中の动漫神作</title><link rel="icon" href="http://vwhm.net/beyond.jpg" type="image/x-icon"/><meta charset="UTF-8"></head><span style="color:#BB0A1E;">面码</span>:"最喜欢仁太了~';
		// response.write(responseText);
		// 响应可以发送多次,最后一次用end()结尾
		// 也可以直接在end方法的参数中,发送响应数据
		response.end(responseText);
	}
	
}
// 注册事件
server.on("request",onReciveFuntion);

function onLaunchFinishFunction () {
	NSLog("服务启动成功",false);
}
// 监听端口,启动服务
// 访问地址:localhost:5267
server.listen(5267, onLaunchFinishFunction);

效果如下:


Node中的JavaScript分为:

1.ECMAScript

 

2.核心模块

所有的NodeJS API地址: https://nodejs.org/dist/latest-v8.x/docs/api/path.html

var fs = require(‘fs’); //加载file system模块的API

var http = require(‘http’); //加载http模块的API

var path = require(‘path’);

var os = require(‘os’);

var net = require(‘net’);

etc…

 

3.第3方模块

require(‘./xxx.js’) ,

xxx.js文件中的exports对象

 

4.用户自定义模块


require演示的示例代码如下:

var os = require('os');
// 8核, 结果是一个数组,里面有8个对象
// 每个对象类似于如下形式
/*
{ model: 'Intel(R) Core(TM) i7-3635QM CPU @ 2.40GHz',
    speed: 2400,
    times: { user: 773130, nice: 0, sys: 509500, idle: 3647550, irq: 0 } 
}
*/
NSLog(os.cpus());

// 内存信息  8589934592
NSLog("内存: " + os.totalmem());

// 文件路径模块
var path = require('path');
var filePath = "/Users/beyond/sg_node/node_07.js";
NSLog("后缀名: " + path.extname(filePath));

效果如下:


require加载模块有3种

1.node自带的核心模块,类似于fs http os path net等

2.用户自己编写的js模块

3.node自带的c++模块


下面示例演示:

node_08.js中,require node_08_a.js

并且node_08_a.js中,又require node_08_b.js

require()中参数必须使用单引号


node_08.js示例代码如下:

// 演示 require加载自己定义的模块
NSLog("before require node_08_a.js",false);
// require()可以省略默认的.js后缀名
// 路径必须以 ./ 或者../开头,且必须用单引号
// 因为,如果省略./ 它就会去核心模块找了

require('./node_08_a.js');
NSLog("after require node_08_a.js");

// 在Node中,没有全局作用域,只有模块作用域,即文件作用域!
// 外部文件 访问不到引用的内部文件
// 内部文件 也访问不到外部文件
// 默认都是封闭的


node_08_a.js示例代码如下:

NSLog("before require node_08_b.js",false);
require('./node_08_b.js');
NSLog("after require node_08_b.js",false);


node_08_b.js示例代码如下:

NSLog("this is node_08_b.js");


效果如下:


在Node中,没有全局作用域,只有模块作用域,即文件作用域!

外部文件 访问不到引用的内部文件

内部文件 也访问不到外部文件

require()可以省略默认的.js后缀名


既然两个文件是默认完全隔离的,那么又是如何 进行通信的呢?

下面例子,node_09.js require了node_09_a.js

同时,被引用node_09_a.js默认自带了一个exports对象 作为两者之间的桥梁

前提是要把文件内部的变量 挂载到 exports对象的属性

node_09.js代码如下:

// 演示 require加载自己定义的模块
NSLog("before require node_09_a.js");

var node09A_exportsObject = require('./node_09_a.js');
// 默认被引用的文件有一个exports对象,作为与外部沟通的桥梁
// 前提是要把那个文件内部的变量挂载到它的exports对象的属性
node09A_exportsObject.showGirl();
NSLog("after require node_09_a.js");


node_09_a.js代码如下:

var girlName = "面码";
var girlAge = 13;
function showGirl () {
	NSLog(girlName + "'s age is " + girlAge + '岁');
}

// 默认有一个exports对象,作为与外部沟通的桥梁
// 前提是要把文件内部的变量挂载到exports对象的属性
exports.showGirl = showGirl;

效果如下:


读取网站图标,并返回给浏览器,针对的url是 /favicon.ico

node_10.js代码如下:

// 导入http模块
var http = require('http');
var server = http.createServer();
function onReciveFuntion (request,response) {
	// 所有的url都是以 / 开头
	var url = request.url
	NSLog("收到浏览器请求,路径是:\n" + url + "\nremote端口是: " + request.socket.remotePort + "\nremoteAddress是: " + request.socket.remoteAddress);
	if(url === '/girl'){
		var girlArr = [
						{girlName:"mathilda",age:12},
						{girlName:"面码",age:15},
						{girlName:"逢坂大河",age:16}
					  ];
	    response.setHeader('Content-Type','text/html;charset=utf-8');
	    response.end('<head><title>beyond心中の动漫神作</title></head>' + JSON.stringify(girlArr));

	}else if(url === '/favicon.ico'){
		// 读取icon图标文件,写到浏览器
		var fs = require('fs');
		// 回调函数
		function callbackFunction (error,data) {
			if (error) {
				// 读取失败
				response.setHeader("Content-Type","text/plain;charset=utf-8");
				response.end("icon读取失败");
			} else{
				// 图片无需指定编码,因为charset只是针对字符串的
				response.setHeader("Content-Type","image/jpeg");
				// response.end()支持字符串或二进制
				response.end(data);
			}
		}
		// 读取网站 图标文件
		fs.readFile('beyond.jpg',callbackFunction);
	}else{
		// 回写的内容 必须是字符串或二进制,不能是 数字,对象,boolean
		var responseText = '<html><head><title>beyond心中の动漫神作</title><link rel="icon" href="beyond.jpg" type="image/x-icon"/><meta charset="utf-8"></head><span style="color:#BB0A1E;">面码</span>:"最喜欢仁太了~';
		// 响应可以发送多次,最后一次用end结尾
		// 也可以直接在end方法的参数中,发送响应数据
		response.end(responseText);
	}
	
}

// 注册事件
server.on("request",onReciveFuntion);
function onLaunchFinishFunction () {
	NSLog("服务启动成功",false);
}

// 监听端口,启动服务
// 访问地址:localhost:5267
server.listen(5267,onLaunchFinishFunction);


附录:

第一天完结, 笔记汇总:

# Node.js 第1天

## 上午总结

– Node.js 是什么
+ JavaScript 运行时
+ 既不是语言,也不是框架,它是一个平台
– Node.js 中的 JavaScript
+ 没有 BOM、DOM
+ EcmaScript 基本的 JavaScript 语言部分
+ 在 Node 中为 JavaScript 提供了一些服务器级别的 API
* 文件操作的能力
* http 服务的能力

## 总结

– Node 中的 JavaScript
+ EcmaScript
* 变量
* 方法
* 数据类型
* 内置对象
* Array
* Object
* Date
* Math
+ 模块系统
* 在 Node 中没有全局作用域的概念
* 在 Node 中,只能通过 require 方法来加载执行多个 JavaScript 脚本文件
* require 加载只能是执行其中的代码,文件与文件之间由于是模块作用域,所以不会有污染的问题
– 模块完全是封闭的
– 外部无法访问内部
– 内部也无法访问外部
* 模块作用域固然带来了一些好处,可以加载执行多个文件,可以完全避免变量命名冲突污染的问题
*

但是某些情况下,模块与模块是需要进行通信的
* 在每个模块中,都提供了一个对象:`exports`
* 该对象默认是一个空对象{}
* 你要做的就是把需要被外部访问使用的成员手动的挂载到 `exports` 接口对象中
* 然后谁来 `require` 这个模块,谁就可以得到模块内部的 `exports` 接口对象
* 还有其它的一些规则,具体后面讲,以及如何在项目中去使用这种编程方式,会通过后面的案例来处理
+ 核心模块
* 核心模块是由 Node 提供的一个个的具名的模块,它们都有自己特殊的名称标识,例如
– fs 文件操作模块
– http 网络服务构建模块
– os 操作系统信息模块
– path 路径处理模块
– 。。。。
* 所有核心模块在使用的时候都必须手动的先使用 `require` 方法来加载,然后才可以使用,例如:
– `var fs = require(‘fs’)`
– http
+ require
+ 端口号
* ip 地址定位计算机
* 端口号定位具体的应用程序
+ Content-Type
* 服务器最好把每次响应的数据是什么内容类型都告诉客户端,而且要正确的告诉
* 不同的资源对应的 Content-Type 是不一样,具体参照:http://tool.oschina.net/commons
* 对于文本类型的数据,最好都加上编码,目的是为了防止中文解析乱码问题
+ 通过网络发送文件
* 发送的并不是文件,本质上来讲发送是文件的内容
* 当浏览器收到服务器响应内容之后,就会根据你的 Content-Type 进行对应的解析处理

– 模块系统
– Node 中的其它的核心模块
– 做一个小管理系统:
+ CRUD
– Express Web 开发框架
+ `npm install express`

未完待续,下一章节,つづく