node.js基础笔记

123 阅读10分钟

一. 为什么要学node

  1. 用户量大
  2. 程序员必备技能
  3. 擅长高并发
  4. 简单
  5. 可实现功能多

node.js可以解析和执行js代码,不是语言,不是库,不是环境,以前只有浏览器可以解析和执行js代码,也就是说现在的js可以完全脱离浏览器运行

node.js没有BOM DOM 在node这个js执行环境中为javascript中为javascript提供了一些服务器级别的操作API,

  1. 例如文件读写
  2. 网络服务的构建
  3. 网络通讯
  4. http服务器
  5. 等处理。。。

node.js具有以下特性

  1. event-driven事件驱动
  2. 非阻塞IO模型(异步)
  3. 轻量和高效

npm是世界上最大的开源库生态系统

绝大多数javascript相关的包都存存放在了npm上,这样做是为了开发人员更方便的去下载使用

npm install jquery

构件与chrome V8引擎

代码只是有特定格式的字符串,引擎可以去执行和解析,

chrome的V8引擎是目前公认执行js最快的引擎

node.js的作者将chrome的v8引擎移植了出来,开发了一个独立的js运行环境

二. node.js基本使用

2.1 文件操作

读取文件

  1. 使用require方法加载fs核心模块

  2. 读取文件

    第一个参数 要读取的文件路径

    第二个参数 回调函数 error data

    读取失败 输出error错误对象 data为空

    读取成功 返回读取的数据

//fs是file-system的简写,就是文件系统的意思
//在node中如果想要进行稳健操作,就必须引入fs这个核心模块

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

fs.readFile('data/app.txt', function(error, data) {
    //使用三目运算符做简单的错误处理
    error ? console.log('读取错误') : console.log(data.toString());
});

写入文件

  1. 使用require方法加载fs核心模块

  2. 写入文件

    第一个参数:要写入的文件路径

    第二个参数:要写入的文件内容

    第三个参数:回调函数

​ 成功:

​ 文件写入成功 error是null

​ 文件写入成功 error就是错误对象

var fs = require('fs');
fs.writeFile('data/write.txt', '今天是学习node.js的第一天', function(error) {
    //使用三目运算符做简单的错误处理
    error ? console.log('文件写入失败') : console.log('文件写入成功');
});

抛出异常throw error

2.2 创建web服务器

// 使用node创建一个web服务器
// 在node中专门提供了一个核心模块:http
// http这个模块的核心作用就是用于创建编写服务器

//1. 使用require方法 加载http核心模块
var http = require('http');

//2. 使用http.createServer()方法创建一个web服务器
//  返回一个Server实例
var server = http.createServer();

//3. 服务器要干嘛
/*发请求
接收请求
处理请求
发送响应*/
//注册request请求事件
//当客户端发请求过来,就会触发request请求事件,执行回调函数
server.on('request', function(req,res) {
    console.log('已经接受到客户端的请求');
});

//4. 绑定端口号,启动服务器
server.listen(8080, function() {
    console.log('服务器启动成功,可以通过http://127.0.0.1:8080或者localhost:8080访问');
});

request请求事件,回调函数有两个参数

  1. Request请求对象请求对象可以用来获取客户端的一些请求信息 例如请求路径

  2. Response响应对象响应对象可以用来给客户端发送响应消息

//  响应对象可以用来给客户端发送响应消息
server.on('request', function(request, response) {
    console.log('已经接受到客户端的请求,请求路径是:' + request.url); //获取请求路径
    //response响应对象有一个方法write可以用来给客户发送响应数据 
    //write可以使用多次,但是最后一定要使用end结束响应,否则客户端会一直等待    
    response.write('hello');
    response.write('node.js');
    //结束响应  
    response.end();
}

JSON,parse() 将json对象转换为js对象

JSON.Stringify() 将js对象转换为json字符串

2.3 Node模块化

Node为js提供了很多服务器级别的api,这些api绝大多数都被宝转到了一个具名的核心模块中了。

例如文件操作的 fs模块,http服务构建的 http模块,path路径操作模块,os操作系统信息获取信息模块

如果想要使用核心模块,就必须在使用前先加载相关的模块

var fs = require('fs');
var http = require('http');//require加载模块

在Node.js中 模块有 1. node自带具名的核心模块 2. 用户编写的核心模块

node使用Common JS作为模块化规范

在node中没有全局作用域,只有模块作用域

外部无法访问内部,内部也无法访问外部,不会因为加载模块导致作用域污染

//a.js
console.log('a start');
//可以省略后缀名
//相对路径的./不可以省略 否则报错 去除之后会把它当成核心模块 后缀名可以省略
require('./b.js');
console.log('a end');
//b.js
console.log('b start');
require('./c.js');
console.log('b end');
//c.js
console.log('c文件被加载执行了');

最终执行结果

PS C:\Users\27843\Desktop\node.js学习\源码\09-简单的模块化> node .\a.js a start b start c文件被加载执行了 b end a end

由于没有模块与模块之间没有作用域拓展,所以我们导出模块使用 exports

require 有两个作用:拿到加载模块并执行里面的代码;拿到被加载文件模块导出的接口对象

每个文件模块里面都提供了一个对象叫做: exports

exports 默认是一个空对象 需要把所有需要外部访问的成员添加到被访问文件exports这个对象中,再由访问文件使用require接收 调用

//a.js
//声明res获取require接受到的exports对象
var res = require('./b');
console.log(res.foo);
console.log(res.add(1, 2));
//b.js
//在exports中添加数据 可以是函数和值
exports.foo = 'loading';
exports.add = function(a, b) {
    return a + b;
}

执行结果:

PS C:\Users\27843\Desktop\node.js学习\源码\09-简单的模块化\加载和导出> node .\a.js loading 3

使用module.export导出属性和方法

实例2:

moduleA

//使用对象解构引入
const { a, b, add } = require('./B')
//直接使用
console.log(a)
console.log(b)
console.log(add(a, b))

moduleB

let a = 10
let b = 20
let add = function (params1, params2) {
    return params1 + params2
}
//使用对象增强写法导出属性和方法
module.exports = { a, b, add }

注意点:

  • module.export只能导出一个对象
  • 使用多个module.export导出结果会后者覆盖前者

2.4 ip地址和端口号

  1. ip地址用来定位计算机
  2. 端口号用来定位具体应用程序
  3. 所有需要联网通信的应用程序都会占用一个端口号
  4. 端口号范围在0-65536(2^16)之间
  5. 在计算机中有一些默认的端口号,最好不要去使用 比如http服务的80
  6. 我们在开发中使用一些简单好记的就行了
  7. 可以同时开启多个服务,但是一定要确保开启了不同的端口号才可以

2.5 发送数据时设置响应头

关于传输中文字符给浏览器时,浏览器显示无法准确显示的问题

在服务端默认发送的数据是utf-8编码的内容,但是浏览器只会按照操作系统默认编码格式去解析,中文操作系统默认编码格式是gbk

在http协议中,content-type就是用来告知对方发送的数据内容是什么类型,使用setHeader方法设置响应头,可以告知浏览器该服务器的编码格式

res.setHeader('Content-Type', 'text/plain;charset=utf-8');

不同类型文件对于content-type是不一样的,我们在传输文件到前端时需要将对应的文件类型添加到相应头中

  • Content-Type
    • 服务器最好把每次响应的数据是什么内容类型都告诉客户端,而且要正确的告诉
    • 不同的资源对应的 Content-Type 是不一样,具体参照:tool.oschina.net/commons
    • 对于文本类型的数据,最好都加上编码,目的是为了防止中文解析乱码问题
  • 通过网络发送文件
    • 发送的并不是文件,本质上来讲发送是文件的内容
    • 当浏览器收到服务器响应内容之后,就会根据你的 Content-Type 进行对应的解析处理

2.6 开放public资源

判断是否以public开头,如果是以public开头的url,则直接访问url对应的文件路径下的文件

let url = req.url
if(url.indexOf('/public/')===0){
    fs.readFile('.'+url,(error,data){
           error? conslole('404'):res.end(data)
    })
}

对于views静态资源里的文件也是有效的 所以静态资源里面的文件的url改为

    <link rel="stylesheet" href="/public/css/bootstrap.css">

2.7 处理GET请求

url模块

//引入
const url = require('url');

//url.parse方法可以帮我们解析url,第二个参数为true可以把我们得到的url信息转换为对象形式 解析
var ret = url.parse('http://localhost:3000/pinglun?name=%E5%B0%8F%E9%A3%9E&message=12312312312312', true);

//使用
console.log(ret);
console.log(ret.query);

运行结果

Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'localhost:3000',
  port: '3000',
  hostname: 'localhost',
  hash: null,
  search: '?name=%E5%B0%8F%E9%A3%9E&message=12312312312312',
  //重要 GET请求的请求体
  query: [Object: null prototype] { name: '小飞', message: '12312312312312' },
  //重要  pathname===req.url
  pathname: '/pinglun',
  path: '/pinglun?name=%E5%B0%8F%E9%A3%9E&message=12312312312312',
  href: 'http://localhost:3000/pinglun?name=%E5%B0%8F%E9%A3%9E&message=12312312312312'
}
[Object: null prototype] { name: '小飞', message: '12312312312312' }

由于GET请求会将请求内容放到url后面,我们使用url模块可以解析得到请求内容

//引入url模块
const url = require('url');
//创建实例接收parse的解析结果 并将其转换为对象形式
var pathObj = url.parse('需要解析的连接',true);
//从pathObj中取出请求体
pathObj.query;

取出请求体之后,我们就可以对请求体进行操作

2.8 浏览器重定向

http状态码

301永久重定向

302临时重定向

res.statusCode = 302;
res.setHeader('Location','重定向路径');
res.end();

三. node后端渲染

node后端渲染就是使用fs文件读取模块读取并解析html格式文件

    //使用url模块解析浏览器请求地址
	var pathObj = url.parse(req.url, true);
	//拿到解析后的文件路径
    var pathname = pathObj.pathname;
	
	//判断文件路径,依据文件路径解析现有html文件
    if (pathname === '/') {
        fs.readFile('./views/index.html', 'utf8', (error, data) => {
            if (error) {
                return console.log('404 not found');
            }
            var ret = template.render(data, {
                comments: comments
            })
            res.end(ret);
        })
    }

后端渲染利于SEO优化

五 node.js连接mysql数据库

5.1 不使用数据库连接池

	//引入MySQL引擎
    const mysql = require('mysql')
    
    //配置MySQL连接信息
    const connection = mysql.createConnection({
        host: 'localhost',
        port: 3309,
        user: 'root',
        password: '123456',
        database: 'library'
    })

    //建立连接
    connection.connect()

	// 操作MySQL 处理操作结果
    connection.query(option.mysqlStatement, (error, result) => {
        if (error) throw error

        if (result) console.log(result)
    })
	
	//关闭连接
    connection.end()

5.2 使用数据库连接池

// 引入数据库引擎
const mysql = require('mysql')

// 创建一个数据库连接池
const pool = mysql.createPool({
    host: 'localhost',
    port: 3309,
    database: 'library',
    user: 'root',
    password: '123456'
})

// 从连接池中获取一个连接
pool.getConnection((err, conn) => {
    if (err) {
        console.log('和mysql数据库建立连接失败')
    } else {
        console.log('和mysql数据库连接成功')
        conn.query('select * from readers', (err2, res) => {
            if (err2) {
                console.log('查询数据库失败')
            } else {
                console.log(res)
                pool.end()
            }
        })
    }
})