Node.js入门以及简单示例。

1、Node.js是什么?

  • 首先Node.js不是一门语言,不是库,不是框架,它是一个javaScript运行时环境,简单来讲就是Node.js可以解析和执行javaScript代码,以前只有浏览器可以解析javaScript代码,也就是说现在的javaScript可以完全脱离浏览器来运行,一切归功于Node.js
  • 浏览器中的javaScript包含EcmaScript(基本语法、if 、var 、function 、Object 、Array ) 、BOMDOM
  • Node.js中的javaScript :没有BOM和DOM、有EcmaScript语法,在Node这个JavaScript执行环境中为JavaScript提供了一些服务级别的操作API(文件读写、网络服务的构建、网络通信、http服务器等
  • Node.js的特性(event-driven事件驱动、non-blocking I/O model非阻塞IO模型、lightweight and effclient轻量级和高效、)
  • Node.js自带的npm是世界上最大的开源库生态系统。npm上绝大多数javaScript相关的包都存放在了npm上,这样做的目的是为了让开发人员更方便的使用。

2、Node.js能做什么?

  • Web服务器后台(游戏服务器、接口服务器)
  • 命令行工具
    • npm (node)
    • git (c语言)
    • hexo (node)
  • 对于前端开发者来说,接触最多的是他的命令行工具
    • 自己写的很少,主要使用别人第三方的
    • webpack
    • gulp
    • npm

3、Node.js安装

3.1、文件读取

  • js读取文件
//浏览器中的javaScript是没有文件操作能力的
//但是node中 的JavaScript具有文件操作的能力

//fs是file-=system的间歇,就是文件系统的意思
//在node中如果想要惊喜文件操作,就必须引进fs这个核心模块
//fs这个核心模块中,就提供了所有的文件操作相关的API
//例如:fs.readFile就是用来读取文件的

//1、使用requre 方法加载fs核心模块
var fs = require('fs')

//读取文件

fs.readFile('./data.txt',function(error,data){
    
    
	console.log(data)
})

  • 效果:返回一串 <Buffer 68 65 6c 6c 6f 20 6e 6f 64 65 0d 0a e4 bd a0 e5 a5 bd 20 4e 6f 64 65 2e 6a 73> ,因为文件中存储的其实都是二进制数据0 1,这里二进制自动转为16进制。可以利用toString()方法转为我们认识的字符。

3.2、文件写入

  • js文件
var fs = require('fs')

//第一个参数:文件路径
//第二个参数:文件内容
//第三个参数:回调函数

fs.writeFile('./你好.md','大家好,好积极把',function(error){
    
    
	console.log('文件写入成功')
})

3.3、简单的http服务

  • 监听端口
// 你可以使用Node非常轻松的构建一个Web服务器
// 在Node中专门提供了一个核心模块:http
// http这个模块的职责就是帮你创建编写服务器

// 1、加载http核心模块

var http = require('http')

// 2、shiyong http.createServer()方法创建一个web服务器
// 返回一个Server实例

var server = http.createServer()

// 3、提供服务(发送请求、处理请求、反馈(发送响应))
// 注册request请求时间
// 当客户端请求过来,就会自动触发服务器的request请求时间,然后执行第二个参数:回调函数

server.on('request',function(){
    
    
	console.log('收到客户端的请求')
})

// 4、绑定端口号,启动服务器

server.listen(3000,function(){
    
    
	console.log('服务器启动成功,可以通过http://127.0.0.1:3000/来进行访问')
})
  • 效果
    在这里插入图片描述
  • 发送响应,修改上面的js文件,添加以下内容
// request请求事件处理函数,需要接受两个参数
// request请求对象 
	// 获取客户端的一些请求信息
// response 响应对象
	//响应对象可以用来给客户端发送响应消息

server.on('request',function(request,response){
    
    
	console.log('收到客户端的请求' + request.url)
	
	// response 对象有一个方法,write可以用来给客户端发送响应数据
	// write可以使用多次,但是最后一定要使用end来结束响应,否则客户端会一直等待

	response.write('hello')
	response.write( 'nodejs')
	
	response.end()
})

  • 效果
    在这里插入图片描述
  • 思考:如何根据URL的不同,响应不同的内容。
var http = require('http')

// 1、创建Server

var server = http.createServer()

// 2、监听request 请求事件,设置请求处理函数
server.on('request' , function(req , res){
    
    
	console.log('收到请求了 , 请求路径是:' + req.url)
//	res.write('hello')
//	res.write(' nodejs')
//	res.end()
//上面的方式比较麻烦,推荐使用更加简单的方式,直接用end的同时发送消息
//根据不同的请求路径响应不同的结果
var url = req.url 

	if(url === '/'){
    
    
		res.end('index.htl')
	}else if(url === '/login'){
    
    
		res.end('index.htl')
	}else{
    
    
		res.end('hello nodejs')
	}
})

// 3、绑定端口号
server.listen(3000,function(){
    
    
	console.log('服务器启动成功 , 可以访问了。。')

})

响应类型只能是字符串或者是二进制数据。

4、Node核心模块

官方文档:官方文档

  • http 网络服务构建模块
  • os 操作系统信息模块
  • fs 文件操作系统模块
  • paths 路径处理模块

要使用对应服务器和客户端,必须使用require(‘XXX’)。

//加载对应的服务模块
var xxx = require('xxx')

4.1、模块系统

  • 在Node中没有全局作用域的概念
  • 在Node中,只能同过require方法来加载执行多个JavaScript脚本文件
  • require加载只能是执行其中的代码,文件与文件之间由于是模块作用域,所以不会有污染的存在
    • 模块完全是封闭的
    • 外部无法访问内部
    • 内部也无法访问外部
  • 模块作用域固然带来了一些好处,可以加在执行多个文件,可以避免变量名冲突污染等,但是在默写情况下,模块与模块之间需要进行通信
  • 在每个模块中,都提供一个对象:‘exports’,该对象默认是一个空对象
  • 外部需要访问使用的成员手动挂载到 ‘exports’ 接口对象中
  • 然后谁来require这个模块,谁就可以得到模块中的 exports 接口对象
  • 例如:

4.1.1、加载require

  • require优先从缓存加载

语法:

//第一个模块文件
exports.foo = 'hello';
//第二个模块文件
var export = require('第一个文件路径')
console.log(export.foo) //这样就可以得到第一个文件的oo属性

两个作用:

  • 执行被加载模块中的代码
  • 得到加载模块中的export导出借口对象

4.1.2、导出export

  • Node 中是模块作用域,默认文件中所有的成员只在当前文件模块有效
  • 对于希望可以被其他模块访问的成员,哦们就需要把这些公开的成员都挂载到export几口对象中就可以。

1、导出多个成员(必须在对象中)

exports.a = 123
exports.b = 'hello'
exports.c = function () {
    
    
	console.log('ccc')
}
exports.d = {
    
    
	foo: 'bar'
}

2、导出单个成员(拿到的就是:函数、字符串)

module.exports = 'hello'

以下情况会覆盖

module.exports = 'hello'
//以这个为准,后者会覆盖前者
module.exports - function (x ,y){
    
    
	return x + y
}

也可以这样导出多个成员

module.exports = {
    
    
	add:function () {
    
    
		return x + y
	},
	str: 'hello'
} 
  • exports 是 module.exports 的一个引用,它们一开始指向的是同一个对象。如果分不清楚,可以不使用export ,直接使用module.exports

4.2、客户端渲染和服务端渲染(模板)

  • 服务端渲染
    在这里插入图片描述
    • 说白了就是在服务端使用模板引擎
    • 模板引擎最早诞生在服务端,后来才发展到前端
  • 客户端渲染
    在这里插入图片描述
  • 客户端渲染和服务端渲染的区别
    • 客户端渲染不利于SEO搜索引擎优化
    • 服务端是可以被爬虫抓取到的,客户端异步渲染是很难被爬虫抓取到的,所以网站多数的两者结合开发的
    • 例如京东的商品列表是采用服务端渲染的,目的是为了SEO搜索引擎优化,而评论是使用客户端渲染,目的是为了用户体验,不需要SEO优化。
    • 如何区分,在网页中查看源代码,能看到数据的就是服务端渲染,反之就是客户端渲染。

5、npm与package.json

5.1、npm

  • npm : node package manager

5.1.1、npm网站

  • npmjs.com

5.1.2、npm命令行工具

  • 可以通过npm --version查看版本
  • 通过npm install --global npm升级版本

5.1.3、常用命令

5.1.4、解决npm被墙的问题

npm install --global cnpm
  • 接下来你安装包的时候把之前的npm替换成cnpm
npm install  jquery
//变成
cnpm install jquery
  • 如果不想安装cnpm,可以使用配置文件的方法,这样也可以。
npm config set registry https://registry.npm.taobao.org

5.2、package.json

  • package.json文件(包描述文件,就像产品说明书一样),里面保存着我们项目需要依赖的包,如果被删除了,我们可以通过该文件找回。
  • package.json可以使用npcnpmnit的方式来自动化出来。
  • 我们通过npm install来加载package.json文件中的依赖

5.3、解决修改完代码自动重启

使用一个第三方命令行工机具,nodemon来帮助我们解决频繁修改代码重启服务器问题,nodemon是一个基于Node.js开发的一个第三方命令行工具,我们使用的时候需要独立安装、

npm install --global nodemon

安装完毕之后,使用:

node xxx.js
//替换成
nodemon xxx.js

6、Express

6.1、起步

6.1.1、安装

npm install --save express
  • hello world
var express = require('express')

//创建 app
var app = express()

app.get('/' , function(req , res){
    
    

	res.send('hello world')
})

app.listen(3000 , function(){
    
    
	console.log('express app is running...')
})
  • 效果

在这里插入图片描述

6.1.2、基本路由

  • get
app.get('/' , function(req ,res){
    
    
	res.send('Hello world')
})
  • post
app.post('/' , function(req ,res){
    
    
	res.send('Get a POST request')
})

6.1.3、静态服务

app.use(express.static('public'))
app.use(express.static('files'))

app.use('/static' , express.static('public'))
app.use('/static' , express.static(path_join(__dirname , 'public')))

6.2、在Express中使用art-template模版

npm install --save art-template
npm install --save express-art-template
  • 配置
app.engine('art' , require('express-art-template'))
  • 使用
app.get('/' , function(req , res){
    
    
	// express 默认会去项目中的views目录中找404.html
	res.render('404.html')
})
  • 如果过希望修改默认的view视图渲染存储目录,可以
// 注意 : 第一个参数views千万不要写错
app.set('views' , '修改的目录路径')

6.2.1、在Express获取表单GET请求体数据

// 获取get请求的数据
var comment = req.query 

6.2.2、在Express获取表单POST请求体数据

在Express中没有内置获取表单POST请求体的API,这里我们需要使用一个第三方包:body-parser.

  • 安装
npm install --save body-parser
  • 配置
var express = require('express')
// 引入中间件包
var bodyParser = require('body-parser')
var app = express()

// 配置
// 加入这个配置之后会在req中增加一个属性 body,就可以获取body中的信息了
app.use(bodyParser.urlencoded({
    
     extended: false }))
// parse application/json
app.use(bodyParser.json())

app.use(function (req, res) {
    
    
  res.setHeader('Content-Type', 'text/plain')
  res.write('you posted:\n')
  // 获取post请求体的数据 req.body
  res.end(JSON.stringify(req.body, null, 2))
})

6.2.3、回调函数

  • 在定义一个方法是,要获取该方法里面一个方法的数据,就需要使用回调函数(获取函数内部的异步操作函数结果
    在这里插入图片描述

6.2.4、在Express中配置express-session 插件

  • 安装
$ npm install express-session
  • 配置
var session = require('express-session')
// 该插件会为 req 请求对象添加一个成员 req.session 默认是一个对象
// 这是最简单的配置
app.use(session({
    
    
// 配置加密字符串,他会在原有的加密基础上和这个字符串拼起来加密
// 谜底是为了增加安全性
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true // 无论你是否使用色碎碎念,都默认给你生成一个加密Cookie
}))
  • 使用
// 添加session
req.session。XXX = XXX
// 获取session
req.session.XXX

默认的Session数据是存储起来的,不会因为服务器重启丢失

7、MongoDB

8、Promise

8.1、Callback hell(回调地狱)

在这里插入图片描述

  • 无法保证顺序的异步代码
var fs = reuqire('fs')

fs.readFile('./data/a.text' , 'utf8' , function(err , data){
    
    
	if (err) {
    
    
		throw err
	}
	console.log(data)
})
fs.readFile('./data/b.text' , 'utf8' , function(err , data){
    
    
	if (err) {
    
    
		throw err
	}
	console.log(data)
})
fs.readFile('./data/c.text' , 'utf8' , function(err , data){
    
    
	if (err) {
    
    
		throw err
	}
	console.log(data)
})
  • 保证代码顺序的回调地狱
var fs = reuqire('fs')


fs.readFile('./data/a.text' , 'utf8' , function(err , data){
    
    
	if (err) {
    
    
		throw err
	}
	console.log(data)
		fs.readFile('./data/b.text' , 'utf8' , function(err , data){
    
    
		if (err) {
    
    
			throw err
		}
		console.log(data)
			fs.readFile('./data/c.text' , 'utf8' , function(err , data){
    
    
			if (err) {
    
    
				throw err
			}
			console.log(data)
		})
	})
})

8.2、Promise-API

  • 为了解决这些问题,所以出现了Promise。(链式调用,不会出现嵌套)
var fs = require('fs')

var p1 = new Promise(function(resolve , reject){
    
    
	fs.readFile('./a.txt' , 'utf8' , function (err , data){
    
    
		if (err) {
    
    
			reject(err)
		}else{
    
    
			resolve(data)
		}
	})
})

var p2 = new Promise(function(resolve , reject){
    
    
	fs.readFile('./b.txt' , 'utf8' , function (err , data){
    
    
		if (err) {
    
    
			reject(err)
		}else{
    
    
			resolve(data)
		}
	})
})

var p3 = new Promise(function(resolve , reject){
    
    
	fs.readFile('./c.txt' , 'utf8' , function (err , data){
    
    
		if (err) {
    
    
			reject(err)
		}else{
    
    
			resolve(data)
		}
	})
})

p1
	.then(function (data) {
    
    
		console.log(data)
		return p2
	} , function (err) {
    
    
		console.log(err)
	})
	// 该方法作为p2的resolve
	.then(function (data) {
    
    
		console.log(data)
		return p3
	} , function (err) {
    
    
		console.log(err)
	})
	// 该方法作为p3的resolve
	.then(function (data) {
    
    
		console.log(data)
	} , function (err) {
    
    
		console.log(err)
	})
	
  • 简单封装
var fs = require('fs')

function pReadFile(filePath){
    
    
	return new Promise(function(resolve , reject){
    
    
		fs.readFile(filePath , 'utf8' , function (err , data){
    
    
			if (err) {
    
    
				reject(err)
			}else{
    
    
				resolve(data)
			}
		})
	})
} 

pReadFile('./a.txt')
	.then(function(data){
    
    
		console.log(data)
		return pReadFile('./b.txt')
	})
	.then(function(data){
    
    
		console.log(data)
		return pReadFile('./c.txt')
	})
	.then(function(data){
    
    
		console.log(data)
	})

猜你喜欢

转载自blog.csdn.net/JISOOLUO/article/details/104069343