1.node基础
-
基于V8引擎渲染JS
-
repl(Read-Evaluate-Print-Loop,输入-求值-输出-循环): repl 交互式解释器 | Node.js API 文档
-
node xxx.js
-
-
event-driven事件驱动(单线程、非阻塞I/O)
-
thread-based system && event-based system
-
EventEmitter
-
2.事件驱动(事件循环机制EventLoop)
/*
* 发布订阅设计模式
*/
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
//=>基于ON的方式,自定义事件和向事件池中追加要处理的方法
myEmitter.on('A', () => {
console.log(1);
});
myEmitter.on('A', () => {
console.log(2);
});
myEmitter.on('B', () => {
console.log(3);
});
//=>基于EMIT触发指定自定义事件中的方法执行
myEmitter.emit('A');
setImmediate / setTimeout / setInterval / process.nextTick
console.log(0);
setTimeout(() => {
console.log(1);
}, 100);
setImmediate(() => {
console.log(3);
}); //=>和setTimeout(0)比较类似 放置到Event Queue的最顶部(也就是主队列执行完,首先执行的就是他)
// setTimeout(() => {
// console.log(2);
// }, 0); //=>0不是立即执行,也需要等待(它是优先于setImmediate)
process.nextTick(() => {
//=>执行下一个任务 放置在主任务队列的末尾,也就是主任务一执行完,先执行process.nextTick,然后再去Event Queue中查找
console.log(4);
});
console.log(5);
-
fs内置板块中的方法
-
process.env.NODE_ENV 设置环境变量
// process.env.NODE_ENV : 设置NODE的全局环境变量
// =>webpack区分开发和生产环境
const env = process.env.NODE_ENV || 'dev';
if (env === 'dev') {
console.log('我是开发环境~~');
} else {
console.log('我是生产环境~~');
}
3.CommonJs模块规范
-
单例模式
const exampleModule = (function () {
function fn() {}
return {
init() {
fn();
}
}
})();
exampleModule.init();
-
AMD (Asynchronous Module Definition)
requirejs.config({
baseUrl: 'js'
});
require(['common', 'utils'], function (common, utils) {
// do something
common.math();
});
-
CMD(Common Module Definition)
define(function(require, exports) {
var a = require('./a');
a.doSomething();
//...
var b = require('./b');
b.math();
});
-
CommonJS
module.exports = {
fn() {},
...
};
let m = require('./M'); //=>想啥时用就啥时候调取,类似于CMD
-
ES6Module
export default {}
import xxx from './xxx'; //=>也需要把它放置在当前模块最开始的位置,类似于AMD
4.模块
封装的fs库
const fs = require('fs'),
path = require('path');
function readFile(pathname, encoding = 'utf8') {
return new Promise((resolve, reject) => {
pathname = path.resolve(pathname);
fs.readFile(pathname, encoding, (err, result) => {
if (err) {
reject(err);
return;
}
resolve(result);
});
});
}
function writeFile(pathname, data, encoding = 'utf8') {
return new Promise((resolve, reject) => {
if (typeof data !== "string") {
data = JSON.stringify(data);
}
pathname = path.resolve(pathname);
fs.writeFile(pathname, data, encoding, err => {
if (err) {
reject(err);
return;
}
resolve();
});
});
}
module.exports = {
readFile,
writeFile
};
fs内置模块
fs内置模块赋予了JS在NODE环境下操作I/O的能力
const fs = require('fs');
// const fsPromises = fs.promises;
=>1.readFile/readFileSync:读取文件中的内容,默认返回的是Buffer流格式,指定utf8让其变为字符串
// const text = fs.readFileSync(`${__dirname}/package.json`, 'utf8');
默认I/O的异步操作是基于回调函数处理的
// fs.readFile(`${__dirname}/package1.json`, 'utf8', (err, result) => {
// if (err) {
// console.dir(err);
// return;
// }
// console.log(result);
// });
// fsPromises.readFile(`${__dirname}/package.json`, 'utf8').then(result => {
// console.log(result);
// }).catch(err => {
// console.log("报错拉~~" + err);
// });
导入自己的FS库
// const fsPromise = require('./lib/myFs');
// fsPromise.readFile('./package1.json')
// .then(result => {
// console.log(result);
// }).catch(err => {
// console.log(err);
// });
写入内容 writeFileSync覆盖式写入(appendFile)
path:不存在会默认创建一个
data:必须是字符串格式
fs.writeFileSync('./1.txt', '你好世界~~', 'utf8');
fs.writeFile('./1.txt', '珠峰培训~~', 'utf8', err => {
// console.log(err);
});
静态资源处理
const http = require('http')
const url = require('url')
const fsPromise = require('../myFs')
const mime = require('mime') // 处理请求格式
/*
* 创建一个WEB服务
* http.createServer() :创建服务
* server.listen():监听端口号
* http://127.0.0.1:9000/ 向当前服务发送请求
*
* 每当客户端向当前服务器发送一个请求,就会触发回调函数执行一次
* req => request :请求对象,存储了客户端传递的信息
* req.headers 存储请求头信息
* req.method 请求方式
* req.url 请求的路径地址(包括问号传参,但没有哈希)
* res => response :响应对象,提供了服务器给客户端返回信息的方法
* res.writeHead 设置响应头
* res.end 结束响应并返回信息
*/
const server = http.createServer((req, res) => {
// const obj = url.parse(req.url, true)
// console.log(obj);
const {
pathname, // 请求的路径名称
query // 问号传参 (对象键值对)
} = url.parse(req.url, true)
pathname = pathname === '/' ? '/index.html' : pathname
// 处理静态资源文件的请求
const suffixREG = /\.([0-9A-Z]+)/i
const suffix = suffixREG.test(pathname) ? suffixREG.exec(pathname)[1] : null
if (suffix) {
const encoding = /^(JPG|JPEG|GIF|PNG)$/i.test(suffix) ? null : 'UTF8'
fsPromise.readFile(`./static${pathname}`).then(result => {
res.writeHead(200, {
'content-type': mime.getType(suffix)
})
res.end(result)
}).catch(err => {
res.writeHead(404, {
'content-type': 'application/json'
})
res.end(JSON.stringify({
code: 1,
codeText: 'not found!'
}))
})
return
}
// API数据接口的处理
// pathname
})
server.listen('9000', () => {
console.log('server is create => 9000');
})
API接口请求的处理
createuser.js
const random = function (n, m) {
return Math.round(Math.random() * (m - n) + n);
};
const area1 = '0123456789';
const area2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const queryPhone = function () {
return new Array(10).fill(null).map(item => {
return area1[random(0, 9)];
}).join('');
};
const queryName = function () {
return new Array(8).fill(null).map(item => {
return area2[random(0, 25)];
}).join('');
};
let arr = [];
for (let i = 2; i <= 93; i++) {
arr.push({
id: i,
name: queryName(),
phone: `1${queryPhone()}`
});
}
const fs = require('fs');
let USER_DATA = fs.readFileSync('./user.json', 'utf8');
USER_DATA = JSON.parse(USER_DATA);
USER_DATA = USER_DATA.concat(arr);
fs.writeFileSync('./user.json', JSON.stringify(USER_DATA), 'utf8');
执行后user.json内容↓
[{ "id": 1, "name": "珠峰培训", "phone": "18310612838", "password": "8376ac810bb9f231d28fcf1f", "passwordPay": "510e33c2291ab2d40877acc8", "pic": "https://app.youpin.mi.com/youpin/static/m/res/images/evaluation_icon_user.png" },
{ "id": 2, "name": "RVTCJQTR", "phone": "12732329581" },
{ "id": 3, "name": "CLWXPPSD", "phone": "16960286463" },
{ "id": 4, "name": "CUUNWINT", "phone": "18473622474" },
{ "id": 5, "name": "MKVZSGOY", "phone": "15882952254" },
{ "id": 6, "name": "BQQSWSST", "phone": "12262637614" },
{ "id": 7, "name": "RKTXHPGR", "phone": "12754776253" },
{ "id": 8, "name": "YUVVWCDI", "phone": "19833633545" },
{ "id": 9, "name": "QUOUIEBT", "phone": "11613887543" },
{ "id": 10, "name": "DRFGIADE", "phone": "17563744829" },
{ "id": 11, "name": "LVGFZQWI", "phone": "13842078830" },
{ "id": 12, "name": "AUIQCGLM", "phone": "17992677456" },
{ "id": 13, "name": "CRMVCEJG", "phone": "16651676467" },
{ "id": 14, "name": "FYXZZDFT", "phone": "16443125470" },
{ "id": 15, "name": "CEEQTQYD", "phone": "11633472140" },
{ "id": 16, "name": "XIUNQUMT", "phone": "12824674365" },
{ "id": 17, "name": "SIOKKKWT", "phone": "15830666632" },
{ "id": 18, "name": "VYWRSFXF", "phone": "17374657413" },
{ "id": 19, "name": "XGJVLADQ", "phone": "15960580634" },
{ "id": 20, "name": "TVYFMOAR", "phone": "11486304577" },
{ "id": 21, "name": "DEQPGDII", "phone": "13143341456" },
{ "id": 22, "name": "KNQTGFNC", "phone": "10234254856" },
{ "id": 23, "name": "TYAUYQCE", "phone": "12015797943" },
{ "id": 24, "name": "TITMLQFD", "phone": "14163626961" },
{ "id": 25, "name": "MQDIAZGP", "phone": "15709717018" },
{ "id": 26, "name": "WKLXHCJT", "phone": "12133484896" },
{ "id": 27, "name": "LLVHRHYX", "phone": "10320540668" },
{ "id": 28, "name": "NPGCXUAH", "phone": "13674899281" },
{ "id": 29, "name": "QGFKMEFJ", "phone": "18134507923" },
{ "id": 30, "name": "YSYLGUSU", "phone": "16497916586" },
{ "id": 31, "name": "UXPBDVCW", "phone": "12433089525" },
{ "id": 32, "name": "IOITTFLM", "phone": "16574297509" },
{ "id": 33, "name": "THEGUQRO", "phone": "18167352438" },
{ "id": 34, "name": "NHWMTXWA", "phone": "13185128668" },
{ "id": 35, "name": "BPTYIFBF", "phone": "17438894135" },
{ "id": 36, "name": "SOXCQOWU", "phone": "13887745387" },
{ "id": 37, "name": "HEGKOHRG", "phone": "12921354565" },
{ "id": 38, "name": "HDXAGUDO", "phone": "17553327276" },
{ "id": 39, "name": "OJNANMBW", "phone": "19801722195" },
{ "id": 40, "name": "BHPLUHXC", "phone": "18747761118" },
{ "id": 41, "name": "JYYEJKHE", "phone": "15383015324" },
{ "id": 42, "name": "JRCIIZGM", "phone": "13533240501" },
{ "id": 43, "name": "YRLNCDFC", "phone": "12060398271" },
{ "id": 44, "name": "VQBVKEMY", "phone": "11855672166" },
{ "id": 45, "name": "YTLGBALR", "phone": "12444747262" },
{ "id": 46, "name": "XIMGSOSN", "phone": "13056500717" },
{ "id": 47, "name": "GXSEIKBR", "phone": "14033482167" },
{ "id": 48, "name": "OCQNZLFB", "phone": "11275321416" },
{ "id": 49, "name": "FJRFGFTX", "phone": "18016357088" },
{ "id": 50, "name": "PGFDGFYG", "phone": "18848732837" },
{ "id": 51, "name": "QDUYHGOZ", "phone": "14575866439" },
{ "id": 52, "name": "RMICFPUK", "phone": "15635622019" },
{ "id": 53, "name": "HSEWKAQM", "phone": "17675414321" },
{ "id": 54, "name": "UYSVLRVG", "phone": "17068636888" },
{ "id": 55, "name": "KNGMDGQF", "phone": "18681673821" },
{ "id": 56, "name": "UDJJCZOD", "phone": "12083156112" },
{ "id": 57, "name": "ZHFEUJAQ", "phone": "13466816547" },
{ "id": 58, "name": "EFMNYXOV", "phone": "19778432124" },
{ "id": 59, "name": "WOCCNVAY", "phone": "14347772101" },
{ "id": 60, "name": "EWRAGKLQ", "phone": "11641633078" },
{ "id": 61, "name": "JHWACNXF", "phone": "15144184777" },
{ "id": 62, "name": "OVLXQOPC", "phone": "15171684606" },
{ "id": 63, "name": "EGFGRNIN", "phone": "14024230457" },
{ "id": 64, "name": "VBWGYECE", "phone": "13553628830" },
{ "id": 65, "name": "UCZKEGBW", "phone": "15651976137" },
{ "id": 66, "name": "NVLEMTCM", "phone": "18147351524" },
{ "id": 67, "name": "YFURITVV", "phone": "12770534365" },
{ "id": 68, "name": "DGAKXTKS", "phone": "10682163476" },
{ "id": 69, "name": "SJZCRYEJ", "phone": "15307756499" },
{ "id": 70, "name": "RPBESRMD", "phone": "19869084262" },
{ "id": 71, "name": "CVJYKVHZ", "phone": "16621234958" },
{ "id": 72, "name": "IELCIKAW", "phone": "16741185194" },
{ "id": 73, "name": "DAMJUIBO", "phone": "17696496235" },
{ "id": 74, "name": "WHPNBGNH", "phone": "18989495633" },
{ "id": 75, "name": "JWSNONWY", "phone": "14256622302" },
{ "id": 76, "name": "GHFFWETD", "phone": "19026420594" },
{ "id": 77, "name": "RIGXAYMV", "phone": "10295383123" },
{ "id": 78, "name": "FYERQMPX", "phone": "18834255238" },
{ "id": 79, "name": "TVOHSDAE", "phone": "13745504882" },
{ "id": 80, "name": "FFQAGAWY", "phone": "12941291116" },
{ "id": 81, "name": "AJGVLDPP", "phone": "16766685444" },
{ "id": 82, "name": "SCOJDCPW", "phone": "11419337107" },
{ "id": 83, "name": "FUUURURK", "phone": "15291340554" },
{ "id": 84, "name": "NQTCOUYY", "phone": "12959464318" },
{ "id": 85, "name": "OIWJYFDH", "phone": "16166574320" },
{ "id": 86, "name": "NLRNVOPQ", "phone": "18514648683" },
{ "id": 87, "name": "HNKFOCFL", "phone": "11422667577" },
{ "id": 88, "name": "HFHMMFYG", "phone": "14462239559" },
{ "id": 89, "name": "FQIKOOGY", "phone": "10751544862" },
{ "id": 90, "name": "DUMMFPHQ", "phone": "16772923141" },
{ "id": 91, "name": "QNPIXLXI", "phone": "16081358929" },
{ "id": 92, "name": "OBCOQEPD", "phone": "12192333402" },
{ "id": 93, "name": "PYYJAGQM", "phone": "14711403266" }
]
server.js执行
const http = require('http');
const url = require('url');
const mime = require('mime');
const qs = require('qs');
const fsPromise = require('./lib/myFs');
/*
* 创建一个WEB服务
* http.createServer():创建服务
* server.listen():监听端口号
* http://127.0.0.1:9000/ 向当前服务发送请求
*
* 每当客户端向当前服务器发送一个请求,就会触发回调函数执行一次
* REQ => request:请求对象,存储了客户端传递的信息
* req.headers 存储请求头信息
* req.method 请求方式
* req.url 请求的路径地址(包含问号传参,但是没有哈希)
* RES => response:响应对象,提供了服务器给客户端返回信息的方法
* res.writeHead 设置响应头
* res.end 结束响应并返回信息
*/
const server = http.createServer(async (req, res) => {
let {
// 请求的路径名称
pathname,
// 问号传参(对象键值对)
query
} = url.parse(req.url, true);
pathname = pathname === '/' ? '/index.html' : pathname;
/* 处理静态资源文件的请求 */
const suffixREG = /\.([0-9A-Z]+)/i;
const suffix = suffixREG.test(pathname) ? suffixREG.exec(pathname)[1] : null;
if (suffix) {
const encoding = /^(JPG|JPEG|GIF|PNG|WAMP|BMP|ICO|SVG|MP3|MP4)$/i.test(suffix) ? null : 'UTF8';
fsPromise.readFile(`./static${pathname}`, encoding).then(result => {
res.writeHead(200, {
'content-type': mime.getType(suffix)
});
res.end(result);
}).catch(err => {
res.writeHead(404, {
'content-type': 'application/json'
});
res.end(JSON.stringify({
code: 1,
codeText: 'not found!'
}));
});
return;
}
/* API数据接口的处理 */
const method = req.method.toUpperCase();
// 先把JSON中的数据都获取到
let USER_DATA = await fsPromise.readFile('./mock/user.json');
USER_DATA = JSON.parse(USER_DATA);
if (pathname === '/api/list' && method === 'GET') {
// 获取客户端问号传递的参数信息
let {
limit = 10,
page = 1
} = query;
let total = USER_DATA.length,
pages = Math.ceil(total / limit),
data = [];
page = parseInt(page);
limit = parseInt(limit);
// 获取指定页面的信息
for (let i = (page - 1) * limit; i < page * limit; i++) {
let item = USER_DATA[i];
if (!item) {
break;
}
data.push(item);
}
// 返回指定内容
res.writeHead(200, {
'content-type': 'application/json'
});
if (data.length === 0) {
res.end(JSON.stringify({
code: 1,
codeText: '没有匹配的数据!'
}));
return;
}
res.end(JSON.stringify({
code: 0,
codeText: 'OK!',
page,
limit,
pages,
total,
data
}));
return;
}
if (pathname === '/api/add' && method === 'POST') {
// 获取请求主体中传递的信息
let text = '';
req.on('data', chunk => {
text += chunk;
});
req.on('end', _ => {
let body = qs.parse(text),
{
name = '',
phone = ''
} = body;
USER_DATA.push({
id: USER_DATA.length === 0 ? 1 : parseInt(USER_DATA[USER_DATA.length - 1]['id']) + 1,
name,
phone
});
res.writeHead(200, {
'content-type': 'application/json'
});
fsPromise.writeFile('./mock/user.json', USER_DATA).then(_ => {
res.end(JSON.stringify({
code: 0,
codeText: 'OK!'
}));
}).catch(err => {
res.end(JSON.stringify({
code: 1,
codeText: '增加失败!'
}));
});
});
return;
}
// 错误的请求地址
res.writeHead(404, {
'content-type': 'application/json'
});
res.end(JSON.stringify({
code: 1,
codeText: 'not found!'
}));
});
server.listen(9000, _ => {
console.log('SERVER IS CREATE => 9000');
});
5.express
utils.js↓
function responseInfo(res, options) {
let config = Object.assign({
code: 0,// 架设成功是0
codeText: 'OK'
}, options)
res.status(200).type('application/json').send(config)
}
module.exports = {
responseInfo
}
myFs.js
const fs = require('fs'),
path = require('path');
function readFile(pathname, encoding = 'utf8') {
return new Promise((resolve, reject) => {
pathname = path.resolve(pathname);
fs.readFile(pathname, encoding, (err, result) => {
if (err) {
reject(err);
return;
}
resolve(result);
});
});
}
function writeFile(pathname, data, encoding = 'utf8') {
return new Promise((resolve, reject) => {
if (typeof data !== "string") {
data = JSON.stringify(data);
}
pathname = path.resolve(pathname);
fs.writeFile(pathname, data, encoding, err => {
if (err) {
reject(err);
return;
}
resolve();
});
});
}
module.exports = {
readFile,
writeFile
};
express↓
const express = require('express') // 引入express框架
const config = require('./config') //
const app = express() // 创建服务
const fsPromise = require('./myFs')
const { responseInfo } = require('./utils')
app.listen(config.port, () => { // 监听端口
console.log(`server is create ${config.port}`);
})
// 中间件:在处理请求之前统一做的事情
app.use(bodyParser.urlencoded({
// 把请求主体传递的信息 x-www-for-urlencoded 变为对象键值对的方式,存储到req.body上(bodyParser中间件完成的事情)
extended: false
}))
app.use(async (req, res, next) => {
req.USER_DATA = await fsPromise.readFile('./mock/user.json')
req.USER_DATA = JSON.parse(req.USER_DATA)
// 处理完当前的事情,让其继续向下匹配处理
next()
})
// API接口的请求处理
app.get('/api/list', (req, res) => {
let {
limit = 10,
page = 1
} = req.query
let total = req.USER_DATA.length,
pages = Math.ceil(total / limit),
data = []
page = parseInt(page)
limit = parseInt(limit)
// 获取指定页面的信息
for (let i = (page - 1) * limit; i < page * limit; i++) {
let item = req.USER_DATA[i]
if (!item) {
break
}
data.push(item)
}
if (data.length === 0) {
responseInfo(res, {
code: 1,
codeText: '没有匹配的数据'
})
return
}
responseInfo(res, {
page,
limit,
pages,
total,
data
})
})
app.post('/api/add', (req, res) => {
let {
name = '',
phone = '',
} = req.body
req.USER_DATA.push({
id: req.USER_DATA.length === 0 ? 1 : parseInt(req.USER_DATA[req.USER_DATA.length - 1]['id']) + 1,
name, phone
})
fsPromise.writeFile('./mock/user.json', req.USER_DATA).then(_ => {
responseInfo(res)
}).catch(err => {
responseInfo(res, {
code: 1,
codeText: '增加失败!'
})
})
})
// 处理静态资源
app.use(express.static('./static'))
app.use((req, res, next) => {
res.status(404).send({
code: 1,
codeText: 'not found'
})
})// 如果请求资源不存在