node.js基础
- nodejs是运行环境。
- npm是包管理工具。
- node采用模块化,所谓模块化,每个node.js为一个模块。
commomJs模块化的规范
- 每个模块都有自己的作用域
- 在自己的模块中,module变量代表自身
- module.exports提供对外的接口
require语法
- /代表绝对路径,./代表相对路径
- 默认后缀为:js json node 且优先级为js>json>node 如果省略后缀的话,则会先查找js查找到之后就引入js,不再查找
例如: require(‘http’)表示导入http包
global 全局对象
所有的module都可以引用。
cnpm
将xxx模块下载到当前目录下
cnpm install xxx
简写
cnpm i xxx
全局
cnpm install xxx -g
局部 生产环境
cnpm install xxx -S
局部 开发环境
cnpm install xxx -D
package.json 项目的描述文件
在node项目中,可以没有node_modules,但是必须要有package.json,有package.json的情况下,可以cd到package.json所在目录,然后在命令行使用
cnpm i
npm上传包
上传包到npm网站,即https://www.npmjs.com/
上传需要切换到需要上传的包的目录内,先登录
npm login
然后使用
npm publish
获取请求的url
利用node进行后端开发,所以需要获取请求的url。
想要实现点击url后端获取到前端的url是什么的功能。
前端界面示例如下
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<a href="http://localhost:8080/content.html?id=2&title=这是文章标题">进入详情页</a>
</body>
</html>
后端监控程序如下:
const http = require("http")
const url = require("url")
const server = http.createServer((req,res) => {
const reqUrl = req.url;
const queryUrl = url.parse(reqUrl,true).query;
console.log(queryUrl);
res.end();
})
server.listen(8080);
获取表单的参数get
- get方法为地址传参
前端界面如下:
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<form method="GET" action="http://localhost:8080">
<input type="text" name="userName">
<input type="password" name="userPassword">
<input type="submit" value="登录">
</form>
</body>
</html>
后端代码如下:
const http = require("http")
const url = require("url")
const server = http.createServer((req,res) => {
// 解决页面上显示的中文乱码
res.writeHead(200,{"Content-Type":"text/html;charset=utf8"})
const reqUrl = req.url;
const queryUrl = url.parse(reqUrl,true).query;
console.log(queryUrl.userName,queryUrl.userPassword)
console.log(queryUrl);
res.end("用户名:" +queryUrl.userName );
})
server.listen(8080);
获取表单的参数 post
- post方法为事件传参
前端界面还采用get的界面,仅仅是 method方法更改为 post
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<form method="POST" action="http://localhost:8080">
<input type="text" name="userName">
<input type="password" name="userPassword">
<input type="submit" value="登录">
</form>
</body>
</html>
post解析参数方法如下:
const http = require("http")
const quertstring = require('querystring')
const server = http.createServer((req,res) => {
// 解决页面上显示的中文乱码
// res.writeHead(200,{"Content-Type":"text/html;charset=utf8"})
let postVal = "";
req.on("data",(chunk)=>{
postVal += chunk;
})
req.on("end",()=>{
console.log(quertstring.parse(postVal))
res.end()
})
})
server.listen(8080);
连接数据库
- 先切换到创建后台工程的文件夹中,使用下面的指令安装mysql相关依赖包
npm install mysql
- 在server.js中连接数据库
const mysql = require("mysql")
const connection = mysql.createConnection({
host:"localhost",
user:"root",
password:"root",
database:"demo",
port:"3306"
})
connection.connect();
connection.query('select * from ad_channellist',(err,results,fields)=>{
if(err) throw err;
console.log(results);
})
connection.end();
登录小案例
此案例首先获取登录的post参数,再根据登录的post参数到数据库进行查询,查询到对应的数据返回登录成功,否则返回登录失败。
const mysql = require("mysql")
const http = require("http")
const quertstring = require('querystring')
const server = http.createServer((req,res) => {
let postVal = "";
req.on("data",(chunk) =>{
postVal = postVal + chunk;
})
req.on("end",()=>{
let formarl = quertstring.parse(postVal);
let name = formarl.userName;
let password = formarl.userPwd;
const connection = mysql.createConnection({
host:"localhost",
user:"root",
password:"root",
database:"demo",
port:3306
})
connection.connect();
connection.query('select * from ad_channellist where channelName=?',[name],(err,results,fields)=>{
if(err) throw err;
console.log(results);
if(results.length > 0){
res.writeHead(200,{"Content-Type":"text/html;charset=utf8"});
res.write("登录成功");
res.end();
}
})
connection.end();
})
})
server.listen(8080);
登录注册小案例
前端界面如下:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>登录界面</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='main.css'>
<script src='main.js'></script>
</head>
<body>
<form method="post" action="http://localhost:8080/login">
<input type="text" name="userName">
<input type="password" name="userPwd">
<input type="submit" value="登录">
</form>
<form method="post" action="http://localhost:8080/register">
<input type="text" name="userName">
<input type="password" name="userPwd">
<input type="submit" value="注册">
</form>
</body>
</html>
实现的过程中,可以根据req.url对前端请求的网址进行区分。每次前端进行请求,都是额外请求一次"/favicon.ico"图标,所以需要对其进行过滤。
node后端实现如下:
const mysql = require("mysql")
const http = require("http")
const quertstring = require('querystring')
const server = http.createServer((req,res) => {
let postVal = "";
req.on("data",(chunk) =>{
postVal = postVal + chunk;
})
console.log(req.url);
if(req.url != "/favicon.ico"){
if(req.url == "/login"){
req.on("end",()=>{
let formarl = quertstring.parse(postVal);
let name = formarl.userName;
let password = formarl.userPwd;
const connection = mysql.createConnection({
host:"localhost",
user:"root",
password:"root",
database:"demo",
port:3306
})
connection.connect();
connection.query('select * from ad_channellist where channelName=?',[name],(err,results,fields)=>{
if(err) throw err;
console.log(results);
if(results.length > 0){
res.writeHead(200,{"Content-Type":"text/html;charset=utf8"});
res.write("登录成功");
res.end();
}
})
connection.end();
})
}else{
if(req.url == "/register"){
req.on("end",()=>{
let formarl = quertstring.parse(postVal);
let name = formarl.userName;
let password = formarl.userPwd;
const connection = mysql.createConnection({
host:"localhost",
user:"root",
password:"root",
database:"demo",
port:3306
})
connection.connect();
connection.query('insert into ad_channellist value (?,?,?,?,?,?)',[0,123,name,132,"132",""],(err,results,fields)=>{
if(err) throw err;
res.writeHead(200,{"Content-Type":"text/html;charset=utf8"});
res.write("添加成功");
res.end();
})
connection.end();
})
}
}
}
})
server.listen(8080);
express框架学习与理解
---------bin 程序的入口文件
------------------------------www 改文件声明端口号,导入APP
---------node_modules node的依赖库
---------public 相关资源
---------routes 路由中声明了网址路径
------------------index.js 路由1中声明了网址路径,可以声明多个网址路径。
------------------route1 路由1中声明了网址路径,可以声明多个网址路径。
---------views 路由中如果是渲染网页,可以将渲染的程序放在views中。
---------app app与routes关联
模板语法:
在routes目录下的index.js中创建一个index.js对象。
router.get('/', function(req, res, next) {
res.render('index', {
title: 'Express' ,
msg: 'hello world'
});
});
index.js对象渲染views中的index.ejs对象,则index.ejs对象中就可以引入
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
<h1><%= msg %></h1>
</body>
</html>
index.js对象修改
修改index中的路径:为/admin
router.get('/admin', function(req, res, next) {
res.render('index', {
title: 'Express' ,
msg: 'hello world'
});
});
index.ejs中文件为:
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<form action="" method="post">
<div class="form-group">
<label for="">用户名</label>
<input type="text">
</div>
<div class="form-group">
<label for="">密码</label>
<input type="password">
</div>
<button>
Login
</button>
</form>
</body>
</html>
最终目标想要实现登录,所以需要使用到数据库,使用到数据库时,程序中需要引入数据库,并且post的action中,需要声明点击后的动作,以及button改成submit,text中声明name
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<form action="/admin/main" method="post">
<div class="form-group">
<label for="">用户名</label>
<input type="text" name="userName">
</div>
<div class="form-group">
<label for="">密码</label>
<input type="password" name="userPwd">
</div>
<input type="submit" value="Login">
</form>
</body>
</html>
文件操作
文件夹异步增删改查
// 创建文件夹
fs.mkdir("logs",(err)=>{
if (err) throw err
console.log("文件夹创建成功!")
})
// 删除文件夹
fs.rmdir("log1",(err)=>{
if (err) throw err
console.log("done!")
})
// 修改文件夹
fs.rename('./logs','./log1 ',()=>{
console.log("文件夹名称修改成功!")
})
// 查看文件夹
fs.readdir('./logs',(err,result)=>{
console.log("error:"+ err + " result:" + result)
})
文件异步增删改查
// 创建文件写,要求必须有上级文件
fs.writeFile('./logs/log1.log', 'hello \n world', (err) => {
if (err) throw err
console.log('done..')
})
// 添加内容
fs.appendFile('./logs/log1.log', '!!!!', (err) => {
if (err) throw err
console.log('done..')
})
// 删除文件
fs.unlink('./logs/log1.log', (err) => {
if (err) throw err
console.log('done..')
})
// 读取文件、读取出的是Buffer,因此需要对声明编码方式或者是使用toString
fs.readFile('./logs/log1.log','utf-8', (err,content) => {
if (err) throw err
console.log('content:' + content)
})
fs.readFile('./logs/log1.log', (err,content) => {
if (err) throw err
console.log('content:' + content.toString())
})
流处理—读写
当文件比较大时,比如说几十M到几百M,此时不能将文件直接写入内存中,需要用到流来进行处理。
使用流处理的时候分为读流与写流。
读流如下
const readStream = fs.createReadStream("./log/file0.log","utf-8")
readStream.on("data", (chunk)=>{
console.log("chunk-",chunk)
})
readStream.on("end", ()=>{
console.log("end")
})
readStream.on("error", (err)=>{
console.log(err)
})
写流如下:
写入hello.txt文件中,写入的标志w,编码utf-8
let ws = fs.createWriteStream("hello.txt", {flags: "w", encoding: "utf-8"});
// 文件打开事件
ws.on('open', function () {
console.log("文件打开")
})
// 文件关闭事件
ws.on("close", function () {
console.log("文件写入完成,关闭")
})
ws.write("hello world 1!",function (err){
if (err){
console.log(err)
}else{
console.log("内容流入完成1")
}
})
ws.write("hello world!2",function (err){
if (err){
console.log(err)
}else{
console.log("内容流入完成2")
}
})
ws.write("hello world3!",function (err){
if (err){
console.log(err)
}else{
console.log("内容流入完成3")
}
})
ws.write("hello world4!",function (err){
if (err){
console.log(err)
}else{
console.log("内容流入完成4")
}
})
ws.end(function (){
console.log("文件流入关闭")
})
读流如下:
单次读取时,默认的大小为65536
// 创建读取流 语法 fs.createReadStream(路径,配置项(可选))
let rs = fs.createReadStream('hello.txt', {flags: 'r', encoding: "utf-8"});
rs.on('open',function (){
console.log("文件读取打开")
})
rs.on('close',function (){
console.log("读取流结束")
})
// 每一批数据流入完成
rs.on('data',function (chunk){
console.log("读取的文件已打开")
console.log(chunk)
})
读取流快速写入到写入流
可以将读取信息直接插入到写入文件中
// 创建读取流 语法 fs.createReadStream(路径,配置项(可选))
let rs = fs.createReadStream('hello.txt', {flags: 'r', encoding: "utf-8"});
let ws = fs.createWriteStream('a.txt', {flags: 'w', encoding: "utf-8"});
rs.on('open',function (){
console.log("文件读取打开")
})
rs.on('close',function (){
console.log("读取流结束")
})
// 每一批数据流入完成
rs.on('data',function (chunk){
console.log("读取的文件已打开")
console.log(chunk)
})
rs.pipe(ws);
node语法
node遵循错误优先的准则, 回调的第一个参数总是err。
async与await
async表示异步的意思。
await表示等待的意思,等待的是一个值或者是Promise对象。
new RegExp(“regexp”,“g”)
g 修饰符用于执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
node执行流程
- node存在一个调用栈,当node后台收到网页发送请求后,网页请求就会进栈。
- 为了加快node的处理速度,一般会将进栈后的请求放入异步模块中进行处理,并且将记录回调。
- 异步模块中某个请求完成之后,将请求的结果发送给事件循环,事件循环再根据某个顺序将回调函数(请求结果)返回给调用栈。
node开发原则
- 捕获并处理每一个错误。
同步代码异常处理。
try…catch…
异步代码异常捕获。
- promise…catch…
- try…catch…
万能的异常捕获。process.on方法,node中所有未被捕获的异常都会再此处理。
兜底方案,不是推荐方案,因为无法向前端返回错误状态。
process.on("uncaughtException",(err)=>{
console.log(err);
})
Array.find()
返回找到的第一个元素,如果没有找到返回undefined
const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element === 12);
console.log(found);
result:
12