nodejs-01
http模块
创建一个http服务器:
// 引入http模块
var http = require('http');
// 创建一个web服务
/**
* request 表示获取url传过来的信息
* response 给浏览器响应信息
*/
http.createServer(function (request, response) {
// 设置响应头
response.writeHead(200, {'Content-Type': 'text/plain'});
// 输出一句话并且结束响应
response.end('Hello World');
}).listen(8081); // 端口
console.log('Server running at http://127.0.0.1:8081/');
const http = require('http')
const url = require('url')
http.createServer((req, res)=>{
// console.log(req.url)
res.writeHead(200, {"Content-type":"text/html;charset='utf-8'"})// 解决中文乱码
res.write(`<head><meta charset="UTF-8"></head>`) // 解决中文乱码
console.log(req.url) // 获取浏览器访问的地址
if(req.url !== '/favicon.ico'){ //当请求了多个url的时候可能无法获取自己所需要的值
let userinfo = url.parse(req.url, true).query
console.log(userinfo);
}
res.end('wdnmd')
}).listen(8111)
url模块中的parse方法:
const url = require('url')
let api = 'http://www.itying.com?name=zhangsan&age=20'
// console.log(url.parse(api, true))
let temp = url.parse(api, true).query
console.log(temp.name);
该方法可以把url中包含的信息解析出来,包括selection、query等
commonjs
自定义模块
把公共的模块抽离成一个单独的js文件,作为一个模块,在该js文件内部通过exports 或者 module.exports暴露属性或者方法
要声明定义一个模块的时候,先在js文件中把相应的功能完成,然后使用exports.函数名(自定义) = 模块中的函数 来使该函数暴露,可以被其他模块引用
function formatApi(api){
return `http://www.itying.com/${api}`
}
exports.formatApi = formatApi
当需要引用一个模块的时候,在js文件头使用require引用该模块即可使用
const http = require('http')
const tools = require('./module/tools.js') // 使用自定义模块,相对路径引用
console.log(tools)
http.createServer((req, res)=>{
// console.log(req.url)
res.writeHead(200, {"Content-type":"text/html;charset='utf-8'"})// 解决中文乱码
res.write(`<head><meta charset="UTF-8"></head>`) // 解决中文乱码
let api = tools.formatApi('api/plist')
res.write(api)
res.end('')
}).listen(8111)
exports和module.exports暴露模块的不同
- exports
exports.get = function(){
}
exports.post = function(){
}
或者:
let obj = {
get:function(){
console.log('从服务器获取数据')
},
post:function(){
console.log('提交数据')
}
}
exports.obj1 = obj
打印结果:
E:\nodejs\demo04>node commonjs02.js
{ obj1: { get: [Function: get], post: [Function: post] } }
- module.exports
let obj = {
get:function(){
console.log('从服务器获取数据')
},
post:function(){
console.log('提交数据')
}
}
// exports.obj1 = obj
module.exports = obj
打印结果
E:\nodejs\demo04>node commonjs02.js
{ get: [Function: get], post: [Function: post] }
模块中方法如果是独立的,则通过exports一个一个进行暴露,如果所有的方法都放在了一个对象里,通过module.exports统一暴露
除了前面提到的const a = require(模块), 还有另一种引用方法
当自定义模块存放在工程路径下的/node_modules 时,引用就可以直接使用模块文件夹的名称,无需使用相对路径
const axios = require('./node_modules/axios/index')
const axios = require('axios') // 两种方法都可以引用同一个模块
但是需要注意的是,这种引用模块的方法默认是寻找axios文件夹下的index.js文件,如果没有该文件则会报错
如果非要用别的名字命名,可以在插件所在目录中使用cmd命令输入 npm init --yes,执行完毕后可以使用模块文件夹名称来引用模块
npm与包
完全符合CommonJs规范的包目录一般包含如下文件
- package.json: 包描述文件
- bin 用于存放可执行二进制文件的目录
- lib: 用于存放JavaScript代码的目录
- doc: 用于存放文档的目录
在工程目录下使用 npm init --yes命令后即可使用npm安装第三方模块
npm i 命令可以查找package.json中工程的依赖,并且为该工程重新安装这些依赖 发送工程文件给他人时,一般不发送node_modules文件夹
npm命令
安装模块 npm install 模块 --save 把依赖添加到package-json文件中 -g 全局安装
指定版本安装模块 npm install 模块@版本号
卸载模块 npm uninstall 模块
查看当前目录下安装的node模块 npm list
package.json
使用 npm init 或者 mpn init --yes生成该文件
{
"name": "demo05",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": { // 依赖
"md5": "^2.3.0",
"silly-datetime": "^0.1.2"
},
"devDependencies":{ //工具
}
}
dependencies下版本号前的标识符意义
- ^表示第一位版本号不变,后面两位取最新
- ~表示前两位不变,最后一个取最新
- *表示全部取最新
fs模块
操作文件的模块
-
fs.stat 检测某一path是文件还是目录
该方法接收两个参数,一个是string类型的path, 另一个是回调函数,回调函数中包括两个参数,分别是error和data,data返回文件或者目录的具体信息
fs.stat('./html', (err, data) => {
if(err){
console.error(err)
return
}
console.log(`是文件:${data.isFile()}`)
console.log(`是目录:${data.isDirectory()}`)
})
输出结果:
E:\nodejs\demo06>node app.js
是文件:false
是目录:true
-
fs.mkdir 创建目录
该方法接收两个参数,一个是要创建的文件夹的路径,另一个是回调函数,回调函数中有一个参数error,错误信息(该方法还有其他options参数)
fs.mkdir('./css', err=>{
if(err){
console.log(err)
return
}
console.log('创建成功')
})
-
fs.writeFile 创建写入文件
该方法接受三个参数,一个是要创建的文件的路径,第二个是写入文件的内容,最后一个是回调函数
如果多次调用该方法,则文件中的内容会被覆盖
fs.writeFile('./html/index.html', 'nihao', err => {
if (err) {
console.log(err)
return
}
})
-
fs.appendFile 追加文件
该方法接受3个参数,第一个是追加内容的文件的路径,第二是追加的内容,最后一个是回调函数
如果要追加的文件不存在,则会自动创建这个文件,多次执行该方法则会一直在文件中追加内容(不覆盖)
fs.appendFile('./css/base.css', 'body{color:red}', err => {
if (err) {
console.log(err)
return
}
console.log('append成功')
})
-
fs.readFile读取文件
该方法接受2个参数,第一个是要读取的文件,第二个参数是回调函数,回调函数内有两个参数,一个是error,另一个是data,表示读取到的内容
fs.readFile('./html/index.html', (err, data)=>{
if (err) {
console.log(err)
return
}
console.log(data)
console.log(data.toString())
})
返回结果:
E:\nodejs\demo06>node app.js
<Buffer 6e 69 68 61 6f>
此处要注意的是,读取到的内容为16进制的buff数据,要转换为String数据使用toString方法即可。
-
fs.readdir 读取目录
该方法接受两个参数,一个是读取目录的路径,另一个是回调函数,err和data
fs.readdir('./html', (err, data)=>{ if (err) { console.log(err) return } console.log(data) })
返回结果
E:\nodejs\demo06>node app.js [ 'index.html' ]
-
fs.rename 重命
该方法接受三个参数,第一个是修改前的文件名,第二个是修改后的文件名,第三个是回调函数err
fs.rename('./html/index.html', './html/index2.html', err=>{ if (err) { console.log(err) return } })
同时该函数也可以实现文件移动操作
fs.rename('./css/index.css', './html/index.css', err=>{ // 此处前后路径不一样,也可以一边移动一边改名 if (err) { console.log(err) return } })
-
fs.rmdir 删除目录
该方法接受两个参数,第一个是要删除的路径,第二个是回调函数
fs.rmdir('./test', err=>{ if (err) { console.log(err) return } })
要注意的是,如果目录中含有目录或者文件,则无法删除该目录
-
fs.unlink 删除文件
该方法接受两个参数,第一个是要删除的文件,第二个是回调函数err
fs.unlink('./html/test.js', err=>{ if (err) { console.log(err) return } })
fs中的方法是异步方法
async、await和Promise
在没有promise之前,要获得异步方法内的值,要通过callback回调函数来获取
es6之后:
let p = new Promise(function(resolve, reject){
setTimeout(function(){
let name = '张三'
resolve(name)
}, 1000)
})
p.then(function(data){
console.log(data)
})
async用于声明一个异步的function。 await用于等待一个异步方法执行完毕,await必须用在async定义的方法里面
// 普通方法
function test(){
return 'wd'
}
console.log(test())
wd
// 异步方法
async function test(){
return new Promise((res, rej)=>{
setTimeout(()=>{
let name = 'zhangsan'
res(name)
}, 1000)
})
}
async function main(){
let data = await test()
console.log(data)
}
main()
异步获取目录数组
let dirArr=[]
let path = '/wwwroot'
async function isDir(path) {
return new Promise((res, rej) => {
fs.stat(path, (error, stats) => {
if (error) {
return
}
if (stats.isDirectory()) {
res(true)
} else {
res(false)
}
})
})
}
// 要注意的是await要用在async里面,即await外部的方法就必须是async
function main(){
fs.readdir(path, async (err, data)=>{
if(err) return
for(let i = 0; i < data.length; i++){
if(await isDir(`${path}/${data[i]}`)){
dirArr.push(data[i])
}
}
console.log(dirArr)
})
}
main()
以流的方式读取写入文件
读取文件——读取流
const fs = require('fs')
let readStream = fs.createReadStream('./data/12345.pdf') // 创建一个读取流
let count = 0 // 流读取文件是以部分读取的方式进行,监听读取了几次
let str = '' // 部分读取,把部分读取出来的内容存放到str里面去
readStream.on('data', data=>{
str+=data // 把内容拼接到data中
count++
})
readStream.on('end', ()=>{
// console.log(str)
console.log(count)
})
写入文件——写入流
const fs = require('fs')
let str = ''
for(let i = 0; i < 500; i++){
str+='我很快就学会node.js了!\n'
}
let writeStream = fs.createWriteStream('./data/output.txt') // 创建写入流
writeStream.write(str) // 以流的方式异步写入文件
//标记写入完成
writeStream.end('说完了')
// 如果要监听写入完成事件必须有writeStream.end('说完了')
writeStream.on('finish', ()=>{
console.log('写入完成')
})
管道流
const fs = require('fs')
let readStream = fs.createReadStream('./data/12345.pdf')
let writeStream = fs.createWriteStream('./data/54321.pdf')
readStream.pipe(writeStream) // 读取流的pipe方法
http,url,fs等模块搭建一个简单http服务器
页面跳转的实现
导入
-
获取url后面传进来的地址
- 对获取的url进行解析,强跳转index.html
- 获取url的后缀,并且使用过滤器过滤,使css、js等文件正常访问
-
通过fs模块读取文件
- 过滤掉无关的url(/favicon.ico)
把获取到的url拼接到文件读取流的参数中,从本地读取html,css等文件
const http = require('http')
const fs = require('fs')
const common = require('./module/common')
const path = require('path')
const url = require('url')
http.createServer(function (req, res) {
// 1. 获取地址
let pathName = url.parse(req.url).pathname
// 判断url是否为/ 如果是的话就把'/index.html'赋给pathName,强行跳转index
pathName = pathName === '/' ? '/index.html' : pathName
// 通过path模块获取url的后缀名
let extName = path.extname(pathName)
// 2. 通过fs模块读取文件,
if (pathName !== '/favicon.ico') { // 先过滤掉其他无关的url
// 把获取到的url拼接到文件读取流的参数中,读取HTML文件
fs.readFile(`./static${pathName}`, (err, data) => {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/html;charset="utf-8"' })
res.end('404')
}
//过滤文件,使不同的静态文件都可以以正确的文件头渲染
let mime = common.getMime(extName)
res.writeHead(200, { 'Content-Type': ''+mime+';charset="utf-8"' })
res.end(data)
})
}
}).listen(8111)
common模块:
//单独函数使用exports导入
exports.getMime=function(extname){
switch(extname){
case '.html': return 'text/html'
case '.css': return 'text/css'
case '.js': return 'text/javascript'
default:
return 'text/html'
}
}