npm(包管理器nodePackageManager)
相当于java中的jdk/maven啥的nvm-windows
command -v nvm
验证是否存在nvm
nvm ls
查看本机的node版本nvm ls-remote
查看远程的node版本// 搭建服务器
let http = require('http')
// 创建服务器
let server = http.createServer(function(request, respose) {
// 设置http响应头-普通文本
respose.writeHead(200, { 'Content-Type' : 'text-plain'})
// 将字符串发送给客户端
respose.end('Hello Node.js')
})
//监听端口号
server.listen(3000, 'localhost')
//再打印个日志
console.log('Node Server started on port 3000');
参考:http://nodejs.cn/api/http.html
使用 HTTP 服务器和客户端,则必须 require('http')
。
以下是我的示例代码
const http = require('http');
const server = http.createServer(function (request, response) {
//捕获请求过来的数据 监听事件的发生
request.on('data', function (chunk) {
data += chunk
})
//当请求全部结束之后,后续不会有新的数据传递过来
request.on('end', function () {
let method = request.method;
// headers本身是一个键值对的形式 用JSON.stringify把它转成Json
let headers = JSON.stringify(request.headers);
//获取http的版本号
let httpVersion = request.httpVersion;
// 获取请求的url
let requestUrl = request.url;
//设置响应的内容
response.writeHead(200, {'Content-Type': 'text/html'})
let responseData = method + ',' + headers + ',' + httpVersion + ',' + requestUrl;
// 把数据发送出去
response.end(responseData);
})
server.listen(3000, function() {
console.log('Node Server started on port 3000');
})
});
node app.js
命令将app.js运行成功后 再执行node app4.js
运行app4.js代码 如下// 搭建客户端
const http = require('http')
//let声明变量 const声明常量
let responseData = ''
// 客户端发起请求
http.request({
'host': 'localhost',
'port': '3000',
'method': 'get'
}, function (response) {
response.on('data', function(chunk) {
responseData += chunk
})
response.on('end', function() {
console.log(responseData);
})
}).end()
const url = require('url');
const urlString = 'http://www.test.com?orderId=12345';
// 解析字符串 把字符串转换成对象
const urlObject = url.parse(urlString);
console.log(urlObject);
const url = require('url');
const urlObject = {
protocol: 'http:',
slashes: true,
auth: null,
host: 'www.test.com',
port: null,
protocol: 'http:',
slashes: true,
auth: null,
host: 'www.test.com',
port: null,
hostname: 'www.test.com',
hash: null,
search: '?orderId=12345',
query: 'orderId=12345',
pathname: '/',
path: '/?orderId=12345',
href: 'http://www.test.com/?orderId=12345'
}
let realUrl = url.format(urlObject)
console.log(realUrl);
querystring.parse(str)
把字符串转化为对象querystring.stringify(obj)
把对象转化为字符串path.join('/hello', '/dssdf', '/safas')
拼接字符串为完整路径// 处理用户服务
class UserService {
login(userName, password) {
console.log(userName, password);
return true
}
}
//这是导出这个类
module.exports = new UserService()
// 搭建客户端
const http = require('http')
//let声明变量 const声明常量
let responseData = ''
// 客户端发起请求
http.request({
'host': 'localhost',
'port': '3000',
'method': 'get',
'path': '/login?userName=zhangsan&password=123456'
}, function (response) {
// 接收用户请求响应输出
response.on('data', function(chunk) {
responseData += chunk
})
response.on('end', function() {
console.log(responseData);
})
}).end()
// 完成node服务器的启动 url的解析 请求参数的获取
const http = require('http')
const querystring = require('querystring')
const url = require('url')
const userService = require('./userService')
// 创建服务器
const server = http.createServer(function(request, response) {
// 接收用户请求数据
let data= ''
request.on('data', function(chunk) {
data += chunk
})
// 没有来源的数据(代码分层)
request.on('end', function() {
// 获取用户请求地址
const requestUrl = request.url
// 获取请求的方法
const requestMethod = request.method
if (requestUrl.includes('login') && requestMethod === 'GET') {
const requestParams = url.parse(requestUrl)
// 拿到用户名和密码对象
const querystringParams = querystring.parse(requestParams.query)
const result = userService.login(querystringParams.userName, querystringParams.password)
console.log(result);
// 服务器发送请求(返回数据给用户)
response.writeHead(200, {'Content-Type': 'text/plain'})
response.end('userName:', querystringParams.userName, 'password:', querystringParams.password)
}
})
})
// 启动服务器
server.listen(3000, function() {
console.log('Server is listening 3000 port');
})
通过npm init创建package.json文件
mkdir node_modules
创建 node_modules文件
npm install(或者是简写i) xx(下载插件)
局部安装
下载的依赖会自动放入dependencies
中, ^表示每次下载时都会下载最新的版本,devDependencies
表示在开发环境时才会用到的依赖,真正部署时是不需要的,从而也能减少生成体积包的大小
npm i xx -g
表示全局安装 局部安装只有当前工程可用
删除依赖模块使用npm uninstall xx
package-lock.json
锁定版本号
rm -rf node_modules
可以删除node_modules
,只要有package.json文件(依赖信息),执行npm i
就会自动下载里面所有依赖
FileSystem模块用于对系统文件及目录进行读写操作。
同步版本与异步版本
对于同步版本与异步版本来说,其在方法的命名上存在一个规则:
xxxx(异步) xxxxSync(同步)
同步
:CPU需要计算10个数据,每计算一个结果后,将其写入磁盘,等待写入成功后,再计算下一个数据,直到完成。异步
:CPU需要计算10个数据,每计算一个结果后,将其写入磁盘,不等待写入成功与否的结果,立刻返回继续计算下一个数据,计算过程中可以收到之前写入是否成功的通知,直到完成。同步代码可以从返回值中拿到执行结果,但是异步代码是不可以获取执行结果。
//异步回调地狱(通过callback获取返回值案例一)
const fs = require('fs')
const path = require('path')
let path1 = path.join(__dirname, 'test.txt')
let path2 = path.join(__dirname, 'test2.txt')
let path3 = path.join(__dirname, 'test3.txt')
fs.readFile(path1, 'utf-8', function(error, data) {
if (error) console.log('error1');
console.log(data);
fs.readFile(path2, 'utf-8', function(error, data) {
if (error) console.log('error2');
console.log(data);
fs.readFile(path3, 'utf-8', function(error, data) {
if (error) console.log('error3');
console.log(data);
})
})
})
promise
依次执行函数Promise
是一个构造函数,有all
(并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调)、race
(只要有一个异步操作执行完毕,就立刻执行 then 回调)、reject
(失败)、resolve
(成功)这几个方法,原型上有then
(链式调用)、catch
(抛出错误)等方法Promise
就是用同步的方式写异步的代码,用来解决回调问题//引入
const fs = require('fs')
const path = require('path')
let path1 = path.join(__dirname, 'test.txt')
let path2 = path.join(__dirname, 'test2.txt')
let path3 = path.join(__dirname, 'test3.txt')
function readFileTest(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf-8', function(error, data) {
resolve(data)
})
})
}
//调用函数readFileTest
let p1 = readFileTest(path1)
p1.then(res => {
console.log(res);
return readFileTest(path2)
}).then(res2 => {
console.log(res2);
return readFileTest(path3)
}).then(res3 => {
console.log(res3);
})
欧克,这样是不是看起来简单多了呢
// Node操纵文件系统是通过一个重要的原生模块来实现的
// 对于fs中的绝大多数api来说,Node都提供了相同功能的两个版本: 同步版本与异步版本
const fs = require('fs')
// 读取文件(异步)
fs.readFile('test.txt', 'utf-8', function(error, data) {
if (error) {
console.log('error occured');
} else {
console.log(data);
}
})
//读取文件(同步)对于同步版本没有回调
try {
let data = fs.readFileSync('text.txt', 'utf-8')
console.log(data);
} catch (error) {
console.log(error);
}
当然是尽量最大可能去使用异步版本, 因为node.js
是一个单线程的,如果方法执行时间比较长,它就会将node唯一的线程给阻塞住,一旦线程被阻塞住,node将无法去为其他任何的请求去服务,除非是万不得已,不然尽可能使用异步版本,因为它不会阻塞线程。
{flag:'a'}
表示追加 === fs.appendFile('info.txt', 'my info', 'utf8', (error) => { if(error) throw error } console.log('success'))
fs.open('test.txt', 'r+', (error, fd) =>{})
(r+)表示可读可写,fd(file descriptor) 表示文件的描述符数字是20
fs.open
打开文件fs.close
关闭文件fs.unlink('hello.txt', (error) => {})
删除文件fs.rename(oldPath, newPath, callback)
重命名fs.mkdir
创建目录,创建多层目录需要将{ recursive: true }
变为true
const fs = require('fs')
//创建目录 { recursive: true }可创建多层目录 默认为false
fs.mkdir('mydir/hello/world', { recursive: true }, (error) => {
if(error) throw error
console.log('success');
})
fs.readdir('./', (error, file) => {})
创建目录fs.access('./app0.js', (error) => {})
检测文件是否存在fs.realpath('app0.js', 'utf8', (error, resolvedPath) => {})
查看目录fs.rmdir('mydir', { recursive: true }, (error) => {})
删除目录const fs = require('fs')
//文件读取流
const readStream = fs.createReadStream('./app12.js', {encoding: 'utf-8'})
// 监听文件打开 fd(file descriptor)表示文件的描述符数字是20
readStream.on('open', (fd) => {
console.log(fd);
})
// 表示已经就绪
readStream.on('ready', () => {
console.log('ready');
})
readStream.on('data', (data) => {
console.log(data);
})
// 表示文件读取完毕
readStream.on('end', () => {
console.log('end');
})
// 文件关闭
readStream.on('close', () => {
console.log('close');
})
// 监听错误信息
readStream.on('error', (error) => {
console.log(error);
})
const fs = require('fs')
// 读取流
const readStream = fs.createReadStream('./app12.js', {encoding: 'utf8'})
// 写入流(将读取到的流 app12.js写入到某个文件中)
const writeStream = fs.createWriteStream('myTest', {encoding: 'utf8'})
// 读取data数据 写入data数据
readStream.on('data', (data) => {
writeStream.write(data, () => {
console.log(data);
})
})
然后就会有一个新的文件myTest文件出现了,里面的内容和app12的内容一样
// 创建一个Buffer的缓存区
// 分配内存
const buffer = Buffer.alloc(128)
// 写入的长度
const length = buffer.write('helloWorld大家', 'utf8')
// 字节长度(一个中文字符占3个字节)
console.log(length); // 16
const str = 'abcde'
const buffer = Buffer.from(str)
// a转换到Buffer中形成二进制数据的时候 就会形成一个字节,如果加上一个中文,就会占3个字节,最后buffer的长度就为8,而字符串的长度是为6
console.log(str.length);
console.log(buffer.length);
console.log(buffer); // 依次对应‘abcde’的ASCII码
//如果要想将buffer的ASCII码显示为它本身 就用toString('utf8')
console.log(buffer.toString('utf8'));
buffer.toString('utf8')
Buffer.from(字符串)
Buffer.concat
)const buffer1 = Buffer.from('hello')
const buffer2 = Buffer.from('hello')
const buffer3 = Buffer.from('hello')
const bufferArray = [buffer1, buffer2, buffer3]
//拼接
const bufferResult = Buffer.concat(bufferArray, buffer1.length + buffer2.length + buffer3.length)
// console.log(bufferResult);
console.log(bufferResult.length); //18
console.log(bufferResult.toString('utf8'));
// 使用typeof判断类型
const str = '你好'
const buffer = Buffer.from('jjj')
const a = true
const obj = {}
const number = 0
console.log(typeof str); // string
console.log(typeof buffer);// object
console.log(typeof a);// boolean
console.log(typeof obj);// object
console.log(typeof number);// number
//通过isBuffer判断是否是Buffer
console.log(Buffer.isBuffer(buffer));//true
console.log(Buffer.isBuffer(obj));//false
node.js对http
模块,tcp
模块提供了很大的支持
HTTP是建立在TCP/IP之上的应用层协议
const net = require('net')
// 和http一样,tcp也是用createServer创建服务器
const server = net.createServer((socket) => {
console.log('client connected');
})
//监听
server.listen(8888, () => {
// 监听成功
console.log('server is listening');
})
// 搭建客户端
const net = require('net')
const clinet = new net.Socket();
clinet.connect('8000', 'localhost', () => {
console.log('connected to server');
})
Nodejs的Events实现了一种观察者模式,其支持了Nodejs的核心机制,且
http / fs / mongoose
等都继承了Events,可以添加监听事件。这种设计模式在客户端的组件编程思想里经常会用到,我们先简单了解下该模式。
观察者模式就是为某一对象添加一监听事件,如on(‘request’, callback),由该对象在符合条件如request时自行触发,浏览器本身已经为dom实现了监听机制。
const http = require('http')
const httpServer = http.createServer()
//观察者模式
// addListener 和 on(别名) 是一样的用法
httpServer.addListener('request', (request, response) => {
if (request.url === '/') {
console.log('addListener');
response.end('end')
}
})
//once代表只执行一次 (当第二次执行的时候将被移除 不会执行)
// httpServer.once('request', (request, response) => {
// if (request.url === '/') {
// console.log('on');
// response.end('end2')
// }
// })
const listener = (request, response) => {
if (request.url === '/') {
console.log('addListener');
response.end('end')
}
}
// 将listener注册到httpServer上
httpServer.on('request', listener)
// 移除观察者removeListener对应的是off(别名)
// httpServer.removeListener('request', listener)
// httpServer.off('request', listener)
// removeAllListeners移除所有的监听器
httpServer.removeAllListeners('request')
httpServer.listen(3000, () => {
console.log('listening to port 3000');
})
// 自定义事件
const EventEmitter = require('events')
const emitter = new EventEmitter()
// newListener表示只要有一个监听器对某个事件注册,就会被触发
emitter.once('newListener', (event, listener) => {
if (event === 'myEvent') {
emitter.on('myEvent', () => {
console.log('hello');
})
}
})
// 注册事件
emitter.on('myEvent', () => {
console.log('world');
})
// 发射
emitter.emit('myEvent')
Node本身能够做到如此高性能的根本原因在于事件(event)的使用,以及对事件监听者(listener, callback)的调用上
while(true) { ... }
Node的单线程
:所谓单线程,指的是Node的逻辑执行主线程是单线程的,既JavaScript代码运行所处的线程,这是个单线程,因为javascript本身只能执行在单线程当中线程池
中操作的// 引入相关的模块
const mysql = require('mysql')
// const uuid = require('uuid')
//创建连接
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'admin123',
database: 'test'
})
// 像mysql数据库发送连接
connection.connect((error) => {
if (error) {
console.log(error);
throw error
} else {
console.log('connection successful!');
}
})
npm install uuid
下载uuid(一般作为唯一值,是由机器硬件和时间等一系列生成的)// 引入相关的模块
const mysql = require('mysql')
const uuid = require('uuid')
//创建连接,开启连接池
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'admin123',
database: 'test'
})
// 像mysql数据库发送连接
connection.connect((error) => {
if (error) {
console.log(error);
throw error
} else {
console.log('connection successful!');
//关闭mysql的连接(end()等待正在执行的事件完成后再关闭)
// connection.end()
// 对数据库表进行操作
// 插入数据
const userId = uuid.v1()
const username = '二号男嘉宾'
const realName = '伍祺峻'
const age = 38
const address = 'chengzhou'
//(?)占位符
connection.query('insert into users set ?', {
id: userId,
username: username,
real_name: realName,
age: age,
address: address
}, (error, result) => {
if (error) {
console.log('insert error' + error);
throw error
} else {
console.log(result);
// 执行对users表的查询
connection.query('select * from users', (error, result) => {
if (error) {
console.log('select error' + error);
throw error
} else {
console.log(result);
connection.end(error => {
if (error) {
console.log('end error' + error);
throw error
}
})
}
})
}
})
}
})
json格式的数据
下载:https://www.mongodb.com/try/download/community
正常安装完成后 访问localhost:27017 出现
就安装成功啦
npm i mongoose
下载mongoose
然后我们与mongoDB建立连接(数据库可以不用事先存在) 以下示例
//引入mongoose
const mongoose = require('mongoose')
// 与mongoDB建立连接(数据库可以不用事先存在)
const uri = 'mongodb://localhost:27017/mytest'
// useNewUrlParser(使用新的url解析器) useUnifiedTopology(统一的Top结构)
mongoose.connect(uri, {useNewUrlParser: true, useUnifiedTopology: true}, error => {
if (error) {
console.log(error);
throw error
} else {
console.log('connect successful!');
}
})
创建好数据库之后 对它执行一些操作示例:
const mongoose = require('mongoose')
// 与mongoDB建立连接(数据库可以不用事先存在)
const uri = 'mongodb://localhost:27017/mytest'
// useNewUrlParser(使用新的url解析器) useUnifiedTopology(统一的结构)
mongoose.connect(uri, {useNewUrlParser: true, useUnifiedTopology: true}, error => {
if (error) {
console.log(error);
throw error
} else {
console.log('connect successful!');
const parentSchema = new mongoose.Schema({
name: String,
age: Number,
address: String
})
const studentSchema = new mongoose.Schema({
name: String,
age: Number,
address: String,
married: Boolean,
parents: parentSchema
})
// 创建模式
mongoose.model('student', studentSchema)
const Student = mongoose.model('student')
const student = new Student({
// 想插入到数据库中的信息
name: 'zhangsan',
age: 20,
address: 'tianj',
married: false,
parents: {
name: 'lisa',
age: 40,
address: 'tianj'
}
})
student.save((error) => {
if (error) {
console.log(error);
throw error
} else {
console.log('save successful');
// 查询所有文档
student.find({}, (error, docs) => {
if (error) {
console.log(error);
throw error;
} else {
console.log(docs);
// 查询成功 关闭连接
// mongoose.connection.close()
// 删除某个文档
docs.forEach(element => {
element.remove();
});
}
})
}
})
}
})
下载地址:https://github.com/tporadowski/redis/releases
安装教程:https://www.runoob.com/redis/redis-install.html
npm i ioredis
下载ioredis
async await
以同步的代码方式实现异步的功能
const Redis = require('ioredis')
const redisKeyPrefix = 'myRedis:info:user:'
class UserRedisDao {
// 获取连接 客户端到服务端
getRedisConnection() {
return new Redis({
host: 'localhost',
port: 6379
})
}
async storeUserId(userSessionId, userId) {
// 获取redis连接
const redis = this.getRedisConnection();
redis.set(redisKeyPrefix + userSessionId, userId, 'ex', 1800, (error, result) => {
redis.quit();
})
}
async getUser(userSessionId) {
const redis = this.getRedisConnection()
return redis.get(redisKeyPrefix + userSessionId, (error, userId) => {
redis.quit();
return userId;
})
}
// 重置信息
async resetUser(userSessionId) {
const redis = this.getRedisConnection()
// 将指定的key指定的过期时间设置成指定的值
redis.expire(redisKeyPrefix + userSessionId, 1800, (error, result) => {
redis.quit();
})
}
// 移除用户已经存在的sessionId
async removeUserSessionId(userSessionId) {
const redis = this.getRedisConnection()
redis.del(redisKeyPrefix + userSessionId, (error, result) => {
redis.quit()
})
}
}
// 导出
module.exports = new UserRedisDao();
const UserRedisDao = require('../db/redis/userRedisDao')
class UserService {
// 调用底层dao的方法
async storeUserId(userSessionId, userId) {
// 在异步方法中等待异步的执行结果 返回之后才能往下走
await UserRedisDao.storeUserId(userSessionId, userId);
}
async getUserSessionId(userSessionId) {
return await UserRedisDao.getUser(userSessionId)
}
async resetUserSessionId(userSessionId) {
await UserRedisDao.resetUser(userSessionId)
}
async removeUserSessionId(userSessionId) {
await UserRedisDao.removeUser(userSessionId)
}
}
module.exports = new UserService()
const userService = require('../service/userService')
const uuid = require('uuid')
class UserController {
// 用户登录的方法
async userLogin(username, password) {
const userId = username;
const userSessionId = uuid.v1();
await userService.storeUserId(userSessionId, userId);
}
async userLogout(userSessionId) {
await userService.userRemove(userSessionId)
}
async userOtherOperation(userSessionId) {
const userId = await userService.getUserSessionId(userSessionId)
console.log(userId, 'from userController');
await userService.resetUserSessionId(userSessionId)
}
}
module.exports = new UserController()
// 使用node服务器 解析用户传来的querystring
const http = require('http')
const url = require('url')
const querystring = require('querystring')
const userController = require('./user/controller/userController')
const server = http.createServer((request, response) => {
let data = ''
request.on('data', (chunk) => {
data += chunk
})
// 当所有的数据都传递完毕
request.on('end', () => {
const requestUrl = request.url;
const requestMethod = request.method;
console.log(requestUrl);
if (requestUrl.includes('login') && requestMethod === 'GET') {
const requestParams = url.parse(requestUrl)
const queryObject = querystring.parse(requestParams.query)
console.log(queryObject);
userController.userLogin(queryObject.username, queryObject.passworld)
response.writeHead(200, {'Content-Type' : 'text/plain'})
response.end('username' + queryObject.username + ',passworld' + queryObject.passworld)
}
})
})
server.listen(3000, () => {
console.log('listening to port 3000');
})
//部分代码
else if (requestUrl.includes('logout') && requestMethod === 'GET') {
// 解析地址
const requestPrams = url.parse(requestUrl)
const queryObject = querystring.parse(requestParams.query)
console.log(queryObject);
// 调用登出方法
userController.userLogout(queryObject.userSessionId)
response.writeHead(200, {'Content-Type' : 'text/plain'})
response.end('user logout')
} else {
// 验证其他两个方法(favicon.ico是网页标题左侧的图标)
if (!requestUrl.includes('favicon.ico')) {
// 解析地址
const requestPrams = url.parse(requestUrl)
const queryObject = querystring.parse(requestParams.query)
console.log(queryObject);
userController.userOtherOperation(queryObject.userSessionId)
response.writeHead(200, {'Content-Type' : 'text/plain'})
response.end('user userOtherOperation')
}
}
一个单个的node.js的实例,运行在单线程上,若想充分利用多核系统,用户需要手动启动node.js的cluater集群
处理相关的负载。cluster是对child_process
的一个封装,可以创建多个子进程帮助node.js主进程分担工作,使用它们协同完成相应的请求和处理,增强了主进程服务的效率,利用多核cpu的威力。
简单的说,主从(Master-Slave)
与进程-线程的关系类似,Master
只有一台机器作为Master
,其他机器作为Slave
,这些机器同时运行组成了集群.Master
作为任务调度者,给多个Slave
分配计算任务,当所有的Slave
将任务完成之后,最后由Master
汇集结果,这个其实也是MapReduce
思想所在。
const cluster = require('cluster');
const http = require('http')
const os = require('os')
const cpuCount = os.cpus().length;
// 如果是父进程
if (cluster.isMaster) {
// fork出来对应的子进程
for (let i = 0; i < cpuCount; ++i) {
// 将当前文件从上至下执行
cluster.fork()
}
cluster.on('exit', (worker, code, signal) => {
console.log(worker.process.pid);
})
} else {
// 子进程 cpuCount次子进程执行这个httpServer
const httpServer = http.createServer((request, response) => {
let data = ''
request.on('data', (chunk) => {
data += chunk
})
request.on('end', () => {
response.writeHead({'Content-Type' : 'text/plain'})
response.end(`${process.pid}`)
})
})
httpServer.listen(3000, () => {
console.log('listening to port 3000');
})
}
基于Node.js平台的下一代Web开发框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。
示例代码:
const Koa = require('koa')
const app = new Koa()
// 中间件
app.use(async (ctx, next) => {
console.log('myFuction start');
// next()表示调用下一个中间件 等待next()都执行完后再执行后面的
await next();
console.log('myFuction finished');
})
// 中间件
app.use(async (ctx, next) => {
console.log('myFuction2 start');
// next()表示调用下一个中间件 等待next()都执行完后再执行后面的
await next();
console.log('myFuction2 finished');
})
// 中间件
app.use(async (ctx, next) => {
console.log('myFuction3 start');
// next()表示调用下一个中间件 等待next()都执行完后再执行后面的
await next();
console.log('myFuction3 finished');
})
// 中间件
app.use(async (ctx) => {
ctx.response.type = 'text/html'
// ctx.response.body ==== ctx.body
ctx.response.body = 'Hello Koa'
ctx.body = 'Hello Koa2
'
})
// 中间件
app.listen(3000, () => {
console.log('app listening to port 3000');
})
运行结果:注意默认请求两次(一个是localhost
,一个是favicon.ico
,请求了一下ico图标)
2. 下载第三方的中间件 npm i @kao/router
3. npm i koa-bodyparser
(能够非常轻松的以Jason的形式拿到请求体)
4. npm i koa-static
(对静态文件的处理)
5. npm i koa-compress
(请求体压缩插件)
6. npm i koa-combine-routers
(组合路由)
7. npm i axios
(处理请求)
8. npm i jsonfile
(在 Node.js 中轻松读/写 JSON 文件。注意:该模块不能在浏览器中使用。)
9. npm i qs
(查询字符串的一个模块解析器)
const path = require('path')
const jsonfile = require('jsonfile')
// __dirname表示当前文件的路径
module.exports = jsonfile.readFileSync(path.join(__dirname, '../projectConfig.json'))
const path = require('path')
const jsonfile = require('jsonfile')
module.exports = jsonfile.readFileSync(path.join(__dirname, 'userServerUrlMapping.json'))
// 解析json文件的
const path = require('path')
const jsonfile = require('jsonfile')
module.exports = jsonfile.readFileSync(path.join(__dirname, 'userRequestUrlMapping.json'))
const axios = require('axios')
const projectConfig = require('../util/projectConfigResolver')
const hostBaseUrl = projectConfig.hostBaseUrl
exports.doHttpGetRequest = function (ctx, requestUrl, params) {
return this.doHttpRequest(ctx, requestUrl, params, 'GET')
}
exports.doHttpPutRequest = function (ctx, requestUrl, params) {
return this.doHttpRequest(ctx, requestUrl, params, 'PUT')
}
exports.doHttpPostRequest = function (ctx, requestUrl, params) {
return this.doHttpRequest(ctx, requestUrl, params, 'POST')
}
exports.doHttpDeleteRequest = function (ctx, requestUrl, params) {
return this.doHttpRequest(ctx, requestUrl, params, 'DELETE')
}
exports.doHttpRequest = function (ctx, requestUrl, params, method) {
if ('GET' === method) {
return axios({
baseURL: hostBaseUrl,
url: requestUrl,
method: 'GET',
params: params
})
} else if ('PUT' === method || 'POST' === method || 'DELETE' === method) {
return axios({
baseURL: hostBaseUrl,
url: requestUrl,
method: method,
data: params
})
}
}
const qs = require('qs')
const baseHttpClinet = require('../common/baseHttpClinet')
const userRequestUrlMappingResolver = require('../config/client/userRequestUrlMappingResolver')
class UserController {
async login(ctx) {
const requestUrl = userRequestUrlMappingResolver.login
console.log(ctx.request.body);
const response = await baseHttpClinet.doHttpPostRequest(ctx, requestUrl, JSON.stringify(ctx.request.body))
const responseData = qs.parse(response.data)
const responseDataCode = responseData.result.code;
if (0 === responseDataCode) {
// 请求成功
ctx.body = responseData
} else {
ctx.body = responseData
}
}
}
module.exports = new UserController()
const Router = require('@koa/router')
const userRouter = new Router()
const userController = require('../controller/userController')
const userServerUrlMappingResolver = require('../config/server/userServerUrlMappingResolver')
userRouter.post(userServerUrlMappingResolver.login, userController.login)
module.exports = userRouter
const Koa = require('koa')
const path = require('path')
const combineRouters = require('koa-combine-routers')
const bodyParser = require('koa-bodyparser')
const koaStatic = require('koa-static')
const compress = require('koa-compress')
const app = new Koa()
const userRouter = require('../router/userRouter')
app.use(compress({
threshold: 2048
}))
// 把请求体中的内容封装成一个一个的对象
app.use(bodyParser())
// 引入静态文件的处理
app.use(koaStatic(path.join(__dirname, '../dist')))
// 模块多
const unifiedRouters = combineRouters(
userRouter
)()
app.use(unifiedRouters)
module.exports = app
require('../app/app').listen(3000)
console.log('Koa2 Server local port 3000');
// 用于真正实现登录请求的逻辑处理
const Koa = require('koa')
const app = new Koa()
app.use(async (ctx) => {
ctx.response.type = 'application/json'
const responseBody = {
result: {
code: 0,
description: 'success'
}, data: {
username: 'zhangsan',
address: 'taiyuan',
age: 20
}
}
ctx.body = JSON.stringify(responseBody)
})
app.listen(4000)
Sync
,并且把读到的内容作为方法返回的结果