nodejs

nodejs简介

nodejs什么是?

为什么学nodejs?

  1. 了解前后端交互流程
  2. 能够自己写api接口
  3. 防止甩锅,明确前后端职责范围
  4. 为了更高的薪资

nodejs的特点

  1. 单线程:
  • 单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。
  • 多线程的好处:可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。
  1. 非阻塞I/O(input/output)
  • 网络请求、数据库处理、文件的读写。。。
  1. 事件驱动

环境配置

nodejs安装

  • Node.js是一个让JavaScript运行在服务器端的开发平台,所以必须首先在本机安装Node.js环境
  • 下载地址
  • 官网术语解释
    1. LTS 版本:Long-term Support 版本,长期支持版,即稳定版。
    2. Current 版本:Latest Features 版本,最新版本,新特性会在该版本中最先加入。
  • 在cmd中,输入 node -v 就能够查看版本号
  • 同时,nodejs 也内置了npm,通过 npm -v 查看版本号
  • NPM是包管理工具,包的结构使您能够轻松跟踪依赖项和版本
  • npm官网
  • 生成 package.json 配置文件
    1. npm init 自定义配置
    2. npm init -y 跳过所有提问,生成默认配置文件

nvm

  • 通过 nvm 安装管理多个nodejs版本
  • nvm常用命令
    1. nvm install version 安装version版本的nodejs,例如:nvm install 8.16.0
    2. nvm uninstall version 卸载version版本的nodejs,例如:nvm uninstall 8.16.0
    3. nvm list 显示所有安装的nodejs版本
    4. nvm list available 显示可以安装的nodejs的版本
    5. nvm use version 使用指定的nodejs版本,例如:nvm use 8.16.0

NPM淘宝镜像

  • 查看npm源地址
    • npm config get registry 默认源:https://registry.npmjs.org/
  • 通过cnpm使用
    • npm install -g cnpm --registry=https://registry.npm.taobao.org
  • 通过npm使用
    • npm config set registry https://registry.npm.taobao.org 推荐

运行程序

js运行环境

  • 浏览器(基本语法、dom、bom、ajax请求…)
  • 服务器(基本语法、操作本地文件、操作数据库…)
  • 限制语言能力的不是语言本身,而是语言的运行环境.

运行nodejs程序

  • 在命令行中执行node指令并回车,进行node的交互式环境(REPL环境)
  • 把javascript代码写在后缀为.js的文件中,命令行执行:node xx.js
  • 按下 ctrl + c 退出当前执行程序
  • node.js是服务端的程序,写的js语句,都将运行在服务器上.
  • node.js没有根目录、没有web容器的概念!

nodemon

  • nodemon会实时监听js代码,发现有修改后自动重启服务器
  • 安装:npm install --global nodemon
  • 之前使用:node xxx.js 改成:nodemon xxx.js

模块化

  1. 内置模块
  2. 第三方模块
  3. 自定义模块

commonjs规范

  • node应用由各种包各种模块组成,采用的commonjs模块规范
  • commonjs加载模块是同步的,模块加载的顺序,按照其在代码中出现的顺序
  • require 方法用于加载模块文件,相当于读入并执行一个js文件
  • module.exports 属性表示当前模块对外输出的接口,让其他文件加载该模块

http模块

  • http 模块 可以用于创建http服务器与http客户端
  1. 创建http服务器
  • 服务器:一台电脑,安装服务器软件,通过ip地址和端口号访问
    htpp://localhost:80 -> 127.0.0.1
    • var http = require('http'); 加载http模块
    • var server = http.createServer(); 创建http服务
    • server.on(‘request’, callback); request事件用于监听来自客户端的请求,callback:回调函数。
    • server.listen(port, host, callback); 启动http服务,监听3000端口
  • 注意:
    1. 在监听request事件中,最后一定要res.end()结束响应。
    2. 浏览器显示·中文可能是乱码·,需设置响应头告诉浏览器显示时所使用的编码,要在res.end()之前设置响应头、状态码、响应内容类型及编码
    res.setHeader("Content-Type","text/plain;charset=utf-8");
    res.setHeader("Content-Type","text/html;charset=utf-8");
    res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});
  • Content-Type:用于定义用户的浏览器如何处理将要加载的数据.
    • text/html 表示响应内容为html的形式,浏览器对响应内容按html解析.
    • text/css 表示响应内容为css的形式,浏览器对响应内容按css解析.
    • text/plain 表示响应内容为纯文本的形式,浏览器不会对其进行其它处理.
    • application/json 表示响应内容为序列化后的 JSON 字符串.
  1. 创建http客户端
  • http.get()
  • http.request()
  • req->request请求对象
  • res->response响应对象
    nodejs没有根目录,没有web容器的概念!!!!!
// 引入模块
const http = require('http')
// 创建http服务
let server = http.createServer()
// 监听server的request事件,有用户请求进来时触发request事件
server.on('request',(req,res)=>{
  // req->request请求对象
  // res->response响应对象

  // console.log(req.url) // path
  if (req.url === '/favicon.ico') {
    return false
  }

  console.log('有用户请求进来了。。。')

  // 设置响应头信息(告诉浏览器响应内容类型--纯文本,字符集为utf-8)
  res.setHeader('Content-Type','text/plain;charset=utf-8')

  // 响应给前端的内容
  res.end('欢迎光临~~~123') // 结束响应
})
// 监听端口号,启动服务
// server.listen(port,host,callback)
server.listen('3000','10.36.136.59',()=>{
  console.log('------------server start------------')
})

fs 模块

  • fs模块提供了用于与文件系统进行交互的API
  • CURD(Create Update Read Del)
  • fs.readFile(file[, options], callback) 读文件
    参数1:要读取的文件路径,必填。
    参数2:读取文件时的选项,比如:文件编码utf8。选填。
    参数3:文件读取完毕后的回调函数,必填。
  • fs.writeFile(file, data[, options], callback) 写文件
    参数1:要写入的文件路径,必填。
    参数2:要写入的数据,必填。
    参数3:写入文件时的选项,比如:文件编码。选填。
    参数4:文件写入完毕后的回调函数,必填。
    writeFile写入文件是先把文件内容清空再写入
    如果要追加写入的话可以使用appendFile函数
  • fs.unlink() 删除文件
  • fs.mkdir() 创建文件夹
  • fs.readdir() 读取文件夹
  • fs.rmdir() 删除文件夹(只能删除空文件夹)
  • fs.rename() 文件重命名
  • fs.stat() 获得文件信息
    stats.isFile()
    stats.isDirectory()
// 同步读取文件,在关键位置捕获错误
try{
  var data = fs.readdirSync('./')
} catch (err){
  console.log(err)
}
console.log(data)

// 异步读取文件
fs.readdir('./',(err,data)=>{
  console.log(data)
})
// 引入模块
const fs = require('fs')

// fs.readFile 异步
// fs.readFileSync 同步

//  异步读取文件
// console.log('111111111111')
// fs.readFile('./test.txt',(err,data)=>{
// // fs.readFile('./test.txt','utf8',(err,data)=>{
//   // 错误的回调优先,err默认值为null,如果有错err是一个错误对象
//   if (err) {// 有错
//     console.log(err)
//     console.log('读取失败')
//   } else {// 没错
//     // console.log(data) // 默认Buffer二进制数据流
//     console.log(data.toString()) // 转成字符串
//   }
// })
// console.log('222222222222')

//  同步读取文件,在关键位置捕获错误 try {} catch(){}
// console.log('111111111111')
// try {// 把容易出错的代码放这里面执行
//   var data = fs.readFileSync('./test1.txt','utf8')
// } catch (err){
//   console.log(err)
// }
// console.log(data)
// console.log('222222222222')

// 异步写文件(覆盖写入),如果当前文件不存在则创建此文件
// fs.writeFile('./test.txt','今天发生了一件大事',(err)=>{
//   if (err) {
//     console.log('写入失败');
//   } else {
//     console.log('写入成功');
//   }
// })

// 异步写文件(追加写入),如果当前文件不存在则创建此文件
// let data = '123456789'
// fs.appendFile('./test.txt',data,(err)=>{
//   if (err) {
//     console.log('写入失败');
//   } else {
//     console.log('写入成功');
//   }
// })

// 删除文件
// fs.unlink('./demo.html',(err)=>{
//   if (err) {
//     console.log('删除失败');
//   } else {
//     console.log('删除成功');
//   }
// })

// 创建文件夹
// fs.mkdir('./hehe',(err)=>{
//     if (err) {
//     console.log('创建失败');
//   } else {
//     console.log('创建成功');
//   }
// })

// 读取文件夹
// fs.readdir('./hehe',(err,data)=>{
//   if (err) {
//     console.log('读取失败');
//   } else {
//     console.log(data);// [ 'haha', 'hehe.html', 'index.js' ]
//   }
// })

// 判断是文件还是文件夹
// fs.stat('./test.txt',(err,stats)=>{
//   if (err) {
//     console.log('获取文件信息失败');
//   } else {
//     console.log( stats.isFile() )// true 代表这个是文件
//     console.log( stats.isDirectory() )// true 代表这个是文件夹
//   }
// })

// 删除文件夹
// fs.rmdir('./tao',(err)=>{
//   if (err) {
//     console.log('删除失败');
//   } else {
//     console.log('删除成功');
//   }
// })

// 修改文件夹名字
fs.rename('./hehe','xixi',(err)=>{
  if (err) {
    console.log('修改失败');
  } else {
    console.log('修改成功');
  }
})

url 模块

  • url 模块 用于处理与解析 URL
  • url叫统一资源定位符
  • url.parse()方法 将url字符串转成对象
  • url.format()方法 将url对象转成字符串
let urlStr = 'https://www.baidu.com/ss/abc?wd=directory&spt=123&issp=888#head';
let urlObj = url.parse( urlStr ); // 默认false,query为字符串
let urlObj  = url.parse(urlStr,true); // 设置true,query为对象
// 引入模块
const url = require('url')

let urlStr = 'https://www.baidu.com/ss/abc?wd=directory&spt=123&issp=888#head'

// 将url字符串转成对象
// let urlObj = url.parse(urlStr,false) // 第二个参数默认为false,query部分为字符串
let urlObj = url.parse(urlStr,true) // 第二个参数默认为true,query部分为对象
console.log( urlObj );
let url_o = {
  protocol: 'https:',
  slashes: true,
  auth: null,
  host: 'www.baidu.com',
  port: null,
  hostname: 'www.baidu.com',
  hash: '#head',
  search: '?wd=directory&spt=123&issp=888',
  // query: 'wd=directory&spt=123&issp=888',
  query: { wd: 'directory', spt: '123', issp: '888' },
  pathname: '/ss/abc',
  path: '/ss/abc?wd=directory&spt=123&issp=888',
  href: 'https://www.baidu.com/ss/abc?wd=directory&spt=123&issp=888#head' 
}

// 将url对象转成字符串
let url_s = url.format(url_o)
console.log(url_s);// https://www.baidu.com/ss/abc?wd=directory&spt=123&issp=888#head

path 模块

  • path模块提供用于·处理文件路径和目录路径·的实用工具
  • path模块的默认操作会根据Node.js程序运行的操作系统而有所不同.
  • path.join(path1[, path2]…) 将多个路径规范化拼接,返回拼接后的路径.
  • path.resolve([…paths]) 将一系列路径解析成绝对路径从右到左解析.
    如果没有参数调用,返回当前工作路径.
  • path.basename(path[, ext]) 返回路径的最后部分(文件名)
    path目标路径,ext要截掉的内容.
  • path.dirname(path) 与basename相对,返回除最后一部分的前面部分路径.
const path = require('path')

// 从右到左拼接

// join拼接返回相对路径
// console.log( path.join('/user','login','index.html') );// '\user\login\index.html'

// console.log( path.join('user','/login','./index.html') );// 'user\login\index.html'

// console.log( path.join('user','../login','./index.html') );// 'login\index.html'

// resolve拼接返回绝对路径
// console.log( path.resolve('/user','login','index.html') );
// D:\user\login\index.html

// console.log( path.resolve('user','/login','./index.html') );
// D:\login\index.html

// console.log( path.resolve('user','../login','./index.html') );
// D:\phpstudy_pro\WWW\test\2005\node\day01\login\index.html

let path1 = 'node/day01/login/index.html'
// 返回路径的最后一部分(文件名)
// console.log( path.basename(path1) );// 'index.html'
// console.log( path.basename(path1,'.html') );// 'index'

// 返回除了path.basename之外的内容
console.log( path.dirname(path1) );// 'node/day01/login'

querystring 模块

  • querystring模块提供用于解析和格式化URL查询字符串的实用工具
  • 将query字符串转成对象
    let str = ‘wd=directory&spt=123&issp=888’;
    let obj = qs.parse( str ); // 默认等价于 qs.parse( str, ‘&’, ‘=’ );
    console.log( obj ); // { wd: ‘directory’, spt: ‘123’, issp: ‘888’ }
  • 将对象转成query字符串
    let obj = { wd: ‘directory’, spt: ‘123’, issp: ‘888’ };
    let str = qs.stringify( obj );
    console.log( str ); // ‘wd=directory&spt=123&issp=888’
  • query字符串编码
    let str = ‘msg=你好&pw=123 456’;
    let res = qs.escape( str );
    console.log( res ); // msg%3D%E4%BD%A0%E5%A5…
  • query字符串解码
    res = qs.unescape( res );
    console.log( res ); // ‘msg=你好&pw=123 456’
// querystring模块
const qs = require('querystring')

let obj1 = { wd: 'directory', spt: '123', issp: '888' }
// 封装一个方法把它转成 'wd=directory&spt=123&issp=888'
// function stringify(obj){
//   let str = ''
//   for (let key in obj){
//     str += key+'='+obj[key]+'&'
//   }
//   str = str.substring(0,str.length-1)
//   return str
// }
// console.log( stringify(obj1) );

// 将对象转成query字符串
// console.log( qs.stringify(obj1) );// 'wd=directory&spt=123&issp=888'
// 等价于
// 第一个参数是要转换的对象
// 第二个参数是键值对之间的分隔符
// 第三个参数是键和值之间的分隔符
// console.log( qs.stringify(obj1,'&','=') );// 'wd=directory&spt=123&issp=888'

// 自定义字符串格式
// console.log( qs.stringify(obj1,'@','-') );// 'wd-directory@spt-123@issp-888'

// query字符串转成对象
// let str = 'wd=directory&spt=123&issp=888'
// console.log( qs.parse(str) );// { wd: 'directory', spt: '123', issp: '888' }
// 等价于
// console.log( qs.parse(str,'&','=') );// { wd: 'directory', spt: '123', issp: '888' }

// let str2 = 'a:1,b:2,c:3'
// console.log( qs.parse(str2,',',':') );//  { a: '1', b: '2', c: '3' }

// 编码后的字符串
let str3 = 'wd=%E7%BE%8E%E5%A5%B3&rsv_spt=1&issp=1'
// 解码
// console.log( qs.unescape(str3) );// 'wd=美女&rsv_spt=1&issp=1'
let str4 = 'wd=美女&rsv_spt=1&issp=1'
// 编码
// console.log( qs.escape(str4) );// 'wd%3D%E7%BE%8E%E5%A5%B3%26rsv_spt%3D1%26issp%3D1'

// 原生js也有编码和解码方法
console.log( escape('你好=123%') );
console.log( unescape('%u4F60%u597D%3D123%25') );

全局变量

  • __dirname 表示当前执行的脚本所在目录的绝对路径

    • 如:D:\phpstudy_pro\WWW\test\GP03\day33
  • __filename 表示当前执行的脚本文件的绝对路径

    • 如:D:\phpstudy_pro\WWW\test\GP03\day33\test.js
  • process是一个全局进程模块

  • console.log( process.env ) 当前的环境信息

  • console.log( process.argv[2] ) 获取输入的命令

// 当前执行脚本的绝对目录
// console.log( __dirname );
// D:\phpstudy_pro\WWW\test\2005\node\day01

// 当前执行脚本的绝对路径
// console.log( __filename );
// D:\phpstudy_pro\WWW\test\2005\node\day01\11-global.js

// console.log( process );
// console.log( process.env );// 当前执行的环境变量
console.log( process.argv[2] );// 用户在命令行输入的自定义命令
// gulp dev -> node gulpfile.js dev

Error对象

  • let err = new Error(‘发送错误了’);
  • console.log(err); 这只是一个错误对象,不会终止代码执行
  • throw err; 抛出错误,会终止代码执行
  • console.log(‘这里不会执行’)
// 创建错误对象,不会影响后面的程序执行
let err = new Error('出错啦')
console.log(err) // 打印错误对象,不会影响后面的程序执行
throw new Error('抛出错误') // 抛出一个错误,会影响后面的程序执行
console.log('程序4')
// 加载模块
const http = require('http')
const fs = require('fs')
const url = require('url')

// 创建http服务,并监听用户请求
http.createServer((req,res)=>{

  // console.log( req.url );// path部分
  // console.log( url.parse(req.url) );// {...}
  let pn = url.parse(req.url).pathname

  if (pn === '/favicon.ico') {
    return
  }

  if (pn === '/') {
    fs.readFile('./index.html','utf8',(err,data)=>{
      if (err) {
        // 设置响应头信息,状态码,响应内容类型,字符集
        res.writeHead(200,{'Content-Type':'text/plain;charset=utf-8'})
        res.end('无法访问首页页面')
      } else {
        // 设置响应头信息,状态码,响应内容类型,字符集
        res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'})
        res.end(data)
      }
    })
  } else if (pn === '/hehe') {
    fs.readFile('./hehe.html','utf8',(err,data)=>{
      if (err) {
        // 设置响应头信息,状态码,响应内容类型,字符集
        res.writeHead(200,{'Content-Type':'text/plain;charset=utf-8'})
        res.end('无法访问hehe页面')
      } else {
        // 设置响应头信息,状态码,响应内容类型,字符集
        res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'})
        res.end(data)
      }
    })
  } else if (pn === '/haha') {
    fs.readFile('./haha.html','utf8',(err,data)=>{
      if (err) {
        // 设置响应头信息,状态码,响应内容类型,字符集
        res.writeHead(200,{'Content-Type':'text/plain;charset=utf-8'})
        res.end('无法访问haha页面')
      } else {
        // 设置响应头信息,状态码,响应内容类型,字符集
        res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'})
        res.end(data)
      }
    })
  } else if (pn === '/c1.jpg') {
    fs.readFile('./c1.jpg',(err,data)=>{
      if (err) {
        // 设置响应头信息,状态码,响应内容类型,字符集
        res.writeHead(200,{'Content-Type':'text/plain;charset=utf-8'})
        res.end('找不到图片')
      } else {
        // 设置响应头信息,状态码,响应内容类型,字符集
        res.writeHead(200,{'Content-Type':'image/jpeg;charset=utf-8'})
        res.end(data)
      }
    })
  }else if (pn === '/index.css') {
    fs.readFile('./index.css',(err,data)=>{
      if (err) {
        // 设置响应头信息,状态码,响应内容类型,字符集
        res.writeHead(200,{'Content-Type':'text/plain;charset=utf-8'})
        res.end('找不到样式')
      } else {
        // 设置响应头信息,状态码,响应内容类型,字符集
        res.writeHead(200,{'Content-Type':'text/css;charset=utf-8'})
        res.end(data)
      }
    })
  } else {
    // 设置响应头信息,状态码,响应内容类型,字符集
    res.writeHead(200,{'Content-Type':'text/plain;charset=utf-8'})
    res.end('404找不到页面')
  }
}).listen(3003,()=>{
  console.log( '-----------server start-----------' )
})

// 用户访问:http://localhost:3003
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值