目录
-
全局变量
- __dirname:表示当前文件所在路径(不包含当前文件)。
- __filename:表示当前文件所在路径(包含当前文件)。
-
回调函数
function callBackFunc(func,name) { func(name); } callBackFunc(name=>console.log(`hello ${name}`),'nodejs');//hello nodejs
-
模块的导入导出
nodejs中的一个js文件就是一个模块
//注:export.js 和 require.js 是同一个文件夹下的文件
/* export.js */
let arr = [1,2,3];
let counter = arr => console.log(`There are ${arr.length} elements in arr.`);
function add(arr){
let all = 0;
arr.forEach(e=>{
all += e;
})
return all;
}
// counter(arr);
// console.log(add(arr));
/* 使用 module.exports 导出一个对象 */
module.exports = {
arr: arr,
counter: counter,
add: add
}
/* require.js */
let stuff = require('./export'); //使用 require 导入一个模块
console.log(stuff.arr); // 1,2,3
stuff.counter(stuff.arr); //There are 3 elements in arr.
console.log(stuff.add(stuff.arr)); //6
-
事件的监听与触发
- 例一:
let events = require ('events');//导入事件库 let myEmitter = new events.EventEmitter(); /* 使用 on 监听 someEvent 事件 */ myEmitter.on('someEvent',message=>console.log(message)); /* 使用 emit 触发 someEvent 事件 */ myEmitter.emit('someEvent','someEvent 事件被触发。');//someEvent 事件被触发。
- 例二:
let events = require ('events');//导入事件库 let util = require('util');//导入工具库 /* 新建一个 Person 构造函数 */ function Person(name,words){ this.name = name; this.words = words; } util.inherits(Person,events.EventEmitter);//util.inherits 表示继承,也可使用ES6的 extends,如下所示: // class Person extends events.EventEmitter{ // constructor(name,words){ // super() // this.name = name; // this.words = words; // } // } let wang = new Person('wang','I love li.'); let li = new Person('li','I love wang.'); let arr = [wang,li]; /* 监听数组中元素的 speak 事件 */ function onSpeak(arr){ arr.forEach(e=>{ e.on('speak',()=>console.log(`${e.name} say: ${e.words}`)); }) } /* 触发数组中元素的 speak 事件 */ function emitSpeak(arr){ arr.forEach(e=>{ e.emit('speak'); }) } onSpeak(arr); emitSpeak(arr); //wang say: I love li. //li say: I love wang.
-
文件的读写操作(同步、异步)
- 同步:fs.readFileSync()、fs.writeFileSync()
- 异步:fs.readFile()、fs.writeFile()
- 代码示例:
/* readMe.txt */ readMe come on! /* test.js */ //同步操作 let fs = require ('fs'); // 导入文件系统库 let readMe = fs.readFileSync('readMe.txt','utf8');//同步读文件操作,第一个参数是文件名,第二个参数是读取文件的编码格式 fs.writeFileSync('writeMe.txt',readMe);//同步写文件操作,第一个参数是文件名,第二个参数是写入内容。注意:如果当前文件夹下没有 writeMe.txt,则会自动创建该文件,并将指定内容写入。 console.log(readMe); console.log('finished.'); /* 执行结果: readMe come on! finished. */ //异步操作 fs.readFile('readMe.txt','utf8',(err,data)=>{ //异步读文件操作,第一个参数是文件名,第二个参数是读取文件的编码格式,第三个参数是一个回调函数。 console.log(data); fs.writeFile('writeMe.txt',data,()=>console.log('writeMe is finished.'));//异步写文件操作,第一个参数是文件名,第二个参数是写入内容,第三个参数是一个回调函数。 }) console.log('finished.'); /* 执行结果: finished. readMe come on! writeMe is finished. */
-
目录的创建、删除;文件的删除
- 异步创建目录:fs.mkdir()
- 异步删除目录:fs.rmdir()
- 异步删除文件:fs.unlink()
- 代码示例(采用两种(Promise、async)异步操作):
- Promise:
let fs = require ('fs'); // 导入文件系统库 /* 在当前目录下创建一个新的目录 stuff,并将当前目录下的 readMe.txt文件写入 stuff中新建的 write.txt文件中。 */ new Promise(resolve=>{ fs.mkdir('stuff',()=>{ //异步创建目录(文件夹)操作,第一个参数为目录名,第二个为回调函数。 console.log('mkdir successfully!') resolve(); }) }) .then(()=>{ return new Promise(resolve=>{ fs.readFile('readMe.txt','utf8',(err,data)=>{ console.log('Read successfully!') resolve(data); }) }) }) .then(v=>{ fs.writeFile('./stuff/writeMe.txt',v,()=>console.log('Write successfully!')); }) .catch(err=>{ console.log(err); }) // /* 删除刚刚创建的 stuff目录。注意:rmdir只能删除空目录,所以先要将目录中的writeMe.txt文件删除。注意:下列代码不能与上述代码一起运行。 */ // new Promise(resolve=>{ // fs.unlink('stuff/writeMe.txt',()=>{ //异步删除文件操作,第一个参数为文件名(带具体路径),第二个为回调函数。 // console.log('Remove writeMe successfully!'); // resolve(); // }) // }) // .then(()=>{ // fs.rmdir('stuff',()=>console.log('Remove stuff successfully!')) //异步删除目录操作,第一个参数为目录名,第二个为回调函数。 // }) // .catch(err=>{ // console.log(err); // })
- async:
let fs = require ('fs'); // 导入文件系统库 /* 在当前目录下创建一个新的目录 stuff,并将当前目录下的 readMe.txt文件写入 stuff中新建的 write.txt文件中。 */ async function mkdirFunc(){ let readMe; await new Promise(resolve=>{ fs.mkdir('stuff',()=>{ console.log('mkdir successfully!') resolve(); }); }) await new Promise(resolve=>{ fs.readFile('readMe.txt','utf8',(err,data)=>{ readMe = data; console.log('Read successfully!'); resolve(); }) }) await new Promise(resolve=>{ fs.writeFile('./stuff/writeMe.txt',readMe,()=>{ console.log('Write successfully!'); resolve(); }); }) console.log('Make finished!') } /* 删除刚刚创建的 stuff目录。注意:rmdir只能删除空目录,所以先要将目录中的writeMe.txt文件删除。 */ async function rmdirFunc(){ await new Promise(resolve=>{ fs.unlink('stuff/writeMe.txt',()=>{ console.log('Remove writeMe successfully!'); resolve(); }) }) await new Promise(resolve=>{ fs.rmdir('stuff',()=>{ console.log('Remove stuff successfully!'); resolve(); }) }) console.log('Remove finished.') } mkdirFunc();//创建 // rmdirFunc();//删除 注意:此函数不能与 mkdirFunc(创建函数)一起运行。
- Promise:
-
流、管道
- 读取流:fs.createReadStream()
- 写入流:fs.createWriteStream()
- 管道:fs.createReadStream().pipe()
- 代码示例:
let fs = require('fs'); // 导入文件系统库 let readStream = fs.createReadStream(__dirname + '/readStream.txt','utf8');//读取流操作,第一个参数为文件名,注意:此处的文件名前一定要有 '/',否则读取文件失败,因为前面的__dirname只是当前路径。第二个参数为读取流编码格式,若省略,则格式为 buffer。 let writeStream = fs.createWriteStream(__dirname + '/writeStream.txt');//写入流操作,参数为文件名。 let streamData = ''; //声明空字符串,用于接收读出来的数据片段。 /* 输出 读取流的内容 */ readStream .on('data',chunk=>{ //监听读取流的 data事件。内容过长时,会多次触发 data 事件,因为流会分段处理数据。 console.log(chunk);//输出当前读取片段 streamData += chunk;//将当前读取片段添加至变量 streamData中。 }) .on('end',()=>{ //监听读取流的 end事件,表明读取操作结束。 console.log(streamData);//输出整个流 }) /* 将读取流的内容 写入 写入流 */ //方法一:流操作 readStream .on('data',chunk=>{ //监听读取流的 data事件。内容过长时,会多次触发 data 事件,因为流会分段处理数据。 writeStream.write(chunk);//分段写入。 }) .on('end',()=>{ //监听读取流的 end事件,表明读取操作结束。 writeStream.end();//结束写入操作 writeStream.on('finish',()=>console.log('WriteStream finished.'));//写入操作已完成 }) //方法一:管道操作 readStream.pipe(writeStream);//使用管道把读出来的流灌输到写入流中。
-
Web服务器
- 创建服务器:http.createServer()
- 监听端口:http.createServer().listen()
- 代码示例(代码较长,细心阅读。 注:下列所有文件都在同一目录下):
/* home.html */ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h1>HOME PAGE</h1> </body> </html> ----------------------------------------------------------------------------------------- /* get.html */ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h1>GET</h1> <form action="/form" method="GET"> name:<input type="text" name="name"> <hr> age:<input type="text" name="age"> <input type="submit" value="提交"> </form> </body> </html> ----------------------------------------------------------------------------------------- /* post.html */ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h1>POST</h1> <form action="/form" method="POST"> name:<input type="text" name="name"> <hr> age:<input type="text" name="age"> <input type="submit" value="提交"> </form> </body> </html> ----------------------------------------------------------------------------------------- /* error.html */ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h1>找不到网页:404</h1> </body> </html>
/* app.js 主调用模块 */ const server = require('./server') //引入自定义服务器模块 const router = require('./router') //引入自定义路由模块 const handler = require('./handler')//引入自定义导航模块 /* 初始化导航对象 */ let handle = {}; handle['/'] = handler.home; handle['/text'] = handler.text; handle['/json'] = handler.json; handle['/home'] = handler.home; handle['/get'] = handler.get; handle['/post'] = handler.post; handle['/form'] = handler.form; /* 调用 启动服务器函数 */ server.startServer(router.route,handle) ----------------------------------------------------------------------------------------- /* server.js 自定义服务器模块*/ const http = require('http') //引入http模块 const url = require('url') //引入url模块 function startServer(route,handle){//启动服务器函数 let server = http.createServer((request,response)=>{//创建 监听服务器 let pathname = url.parse(request.url).pathname;//提取 url中的pathname route(handle,request,response,pathname); }) server.listen(3000,'127.0.0.1');//监听端口。'127.0.0.1'相当于本地localhost。 console.log('Server started.'); } module.exports.startServer = startServer; ----------------------------------------------------------------------------------------- /* router.js 自定义路由模块 */ const fs = require('fs') function route(handle,request,response,pathname){ if(typeof handle[pathname] == 'function'){ handle[pathname](request,response); }else{ console.log('Received error'); /* 路由覆盖错误页面 */ response.writeHead(404,{'Content-Type': 'text/html'}); fs.createReadStream(__dirname + '/error.html').pipe(response); } } module.exports.route = route; ----------------------------------------------------------------------------------------- /* handler.js 自定义导航模块 */ const fs = require('fs') const querystring = require('querystring') //引入querystring模块,用于序列化url const url = require('url') function text(request,response){ let str = 'Hello NodeJS.' console.log('Received text'); response.writeHead(200,{'Content-Type': 'text/plain'});//设置响应头的数据类型。此处传输 普通文本。 response.end(str);//此行还可写成下列格式: /* response.write(str); response.end();//记得 end,否则浏览器会一直等待服务端write。 */ } function json(request,response){ let jsonObj = { name: 'wang', age: 21 } console.log('Received json'); response.writeHead(200,{'Content-Type': 'application/json'});//设置响应头的数据类型。此处传输 json格式。 response.end(JSON.stringify(jsonObj)); } function home(request,response){ console.log('Received home'); response.writeHead(200,{'Content-Type': 'text/html'});//设置响应头的数据类型。此处传输 html格式。 fs.createReadStream(__dirname + '/home.html','utf8').pipe(response);//使用流传输html文件。 } function get(request,response){ console.log('Received get'); response.writeHead(200,{'Content-Type': 'text/html'});//设置响应头的数据类型。此处传输 html格式。 fs.createReadStream(__dirname + '/get.html','utf8').pipe(response);//使用流传输html文件。 } function post(request,response){ console.log('Received post'); response.writeHead(200,{'Content-Type': 'text/html'});//设置响应头的数据类型。此处传输 html格式。 fs.createReadStream(__dirname + '/post.html','utf8').pipe(response);//使用流传输html文件。 } function form(request,response){ let dataArr = [];//用于存放传来的data片段 request .on('data',chunk=>{ dataArr.push(chunk);//将data片段push进dataArr(官方推荐写法) }) .on('error',err=>console.log(err)) .on('end',()=>{ if(request.method === 'GET'){ let query = url.parse(request.url,true).query;//提取 url中的参数 console.log('Received form GET'); response.writeHead(200,{'Content-Type': 'application/json'});//设置响应头的数据类型。此处传输 json格式 response.end(JSON.stringify(query)) }else if(request.method === 'POST'){ console.log('Received form POST'); response.writeHead(200,{'Content-Type': 'application/json'});//设置响应头的数据类型。此处传输 json格式 let data = Buffer.concat(dataArr).toString();//将dataArr中的数据提取出来,等同下行 /* let data = dataArr.toString();//将dataArr中的数据提取出来 */ response.end(JSON.stringify(querystring.parse(data)))//先使用querystring.parse()将data转化为对象。再使用JSON.stringify()把其转换为JSON字符串。 } }) } module.exports = { text:text, json: json, home: home, get: get, post: post, form: form }
-
npm
知道一个项目的 package.json 文件,只需在当前文件夹使用 npm install 命令,即可下载所有模块。