node.js

1.node基础

  • 基于V8引擎渲染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'
    })
})// 如果请求资源不存在

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值