nodejs入门
1、模块(模块的导入导出)
导出:
新建./count.js
文件,内容为:
const counter = function (n) {
return `counter: ${n}`
}
const adder = function (a, b) {
return `adder: a + b = ${a + b}`
}
const PI = 3.14
/**[第一种导出方式]:只能导出一个;导入方式参照app.js中的第一种导入方式 */
module.exports = counter
/**[第二种导出方式]:导出多个 */
module.exports.counter = counter
module.exports.adder = adder
module.exports.PI = PI
/**[第三种导出方式]:导出多个 */
module.exports = {
counter,
adder,
PI
}
导入:
新建./app.js
文件,内容为:
app.js:
/**[第1种导入方式] start*/
var counter = require('./count.js')
console.log( counter(1) ) //result: counter: 1
/**[第1种导入方式] end*/
/**[第2种导入方式] start*/
var count = require('./count.js')
console.log( count.counter(1) ) //result: counter: 1
console.log( count.adder(2, 3) ) //result: adder: a + b = 5
console.log( count.pi ) //result: 3.14
/**[第2种导入方式] end*/
/**[第3种导入方式] start*/
var { counter, adder, pi } = require('./count.js')
console.log( counter(1) ) //result: counter: 1
console.log( adder(2, 3) ) //result: adder: a + b = 5
console.log( pi ) //result: 3.14
/**[第3种导入方式] end*/
然后使用node执行:node ./app.js
,就可以看到相应的结果。
总结:
1.导出单个文件:module.exports = counter
,导入使用var counter = require('./count.js')
。
2.导出多个文件A:module.exports.counter = counter;
,导入使用var count = require('./count.js')
;
3.导出多个文件B:module.exports = { counter };
,导入使用var { counter } = require('./count.js')
;
2、事件
事件监听和触发
在app.js
中加入:
var events = require('events');
var myEmitter = new events.EventEmitter();
myEmitter.on('someEvent', function (message) {
console.log(message)
})
myEmitter.emit('someEvent', 'the event was emitted')
实例
var events = require('events');
var util = require('util')
function Person (name) {
this.name = name
}
util.inherits(Person, events.EventEmitter);
var zhang3 = new Person('zhang3')
var li4 = new Person('li4')
var wang5 = new Person('wang5')
var persons = [zhang3, li4, wang5]
persons.forEach(person => {
person.on('speak', (message) => {
console.log( person.name + ' said: ' + message )
})
})
zhang3.emit('speak', 'hi');
li4.emit('speak', 'i want a curry')
3、读写文件(同步、异步)
同步操作
// 读取
var hello = fs.readFileSync('./hello.txt', 'utf8')
console.log( hello )
console.log(111)
// 写入
fs.writeFileSync('writeMe.txt', hello) //会创建一个./writeMe.txt文件,内容为:hello.txt
异步操作
// 读取-写入
fs.readFile('./hello.txt', 'utf8', function (err, data) {
console.log( data )
fs.writeFile('writeMe.txt', data, function () {
console.log('写入成功') //会创建一个./writeMe.txt文件,内容为:hello.txt
})
})
console.log(111)
4、创建和删除目录
var fs = require('fs')
fs.mkdirSync('stuff') //创建目录
fs.rmdirSync('stuff') //删除目录
实践
创建一个./stuff目录,并读取./hello.txt中的内容,将其存入新建的./stuff/hello.txt文件中。
fs.mkdir('stuff', function () {
console.log('文件夹创建成功')
fs.readFile('./hello.txt', function(err, data) {
console.log('文件读取成功')
if(!err) {
fs.writeFile('./stuff/hello.txt', data, function () {
console.log('文件创建成功')
})
} else {
console.log( 'read file error' )
}
})
})
5、流和管道
优点:处理数据、提高性能
流读写文件
var fs = require('fs')
var stream = fs.createReadStream(__dirname + '/count.js', 'utf8')
var stream2 = fs.createWriteStream(__dirname + '/write.js')
var n = ''
stream.on('data', function (chunk) {
//chunk数据流块
n += chunk
stream2.write(chunk)
})
stream.on('end', function () {
console.log( n ) //输出所有内容
})
// 写入内容
var writeData = 'hello world';
stream2.write(writeData, 'utf8');
stream2.end();
stream2.on('finish', function () {
console.log('finished')
})
// 管道|拷贝内容
stream.pipe(stream2)
6、web服务器part1介绍
const http = require('http')
var server = http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
/**[第一种方式] */
res.write('Hello World')
res.end();
/**[第二种方式] */
res.end('Hello World');
})
server.listen(3000)
7、web服务器part2响应JSON
const http = require('http')
var server = http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'application/json' });
var obj = {
name: 'david',
age: 12,
job: 'web'
}
res.end(JSON.stringify(obj));
})
server.listen(3000)
8、web服务器part3响应html页面
const http = require('http')
const fs = require('fs')
const path = __dirname + '/index.html'
var server = http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
var htmlFile = fs.createReadStream(path, 'utf8')
htmlFile.pipe(res)
})
server.listen(3000)
9、web服务器part5模块化代码
新建./server.js
const http = require('http')
const fs = require('fs')
const path = __dirname + '/index.html'
function startServer () {
var server = http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
var htmlFile = fs.createReadStream(path, 'utf8')
htmlFile.pipe(res)
})
server.listen(3000)
}
exports.startServer = startServer
./app.js
var server = require('./server')
server.startServer()
10、web服务器part5路由
./app.js
var server = require('./server')
server.startServer()
./server.js
const http = require('http')
const fs = require('fs')
function startServer () {
var onRequest = function (req, res) {
if(req.url === '/' || req.url === '/home') {
// 是 / or /home 返回index.html
res.writeHead(200, { 'Content-Type': 'text/html' });
const path = __dirname + '/index.html'
fs.createReadStream(path, 'utf8').pipe(res)
} else if (req.url === '/review') {
// 是 /review review.html
res.writeHead(200, { 'Content-Type': 'text/html' });
const path = __dirname + '/review.html'
fs.createReadStream(path, 'utf8').pipe(res)
} else if (req.url === '/api/v1/records') {
// 是/api/v1/records 返回json
res.writeHead(200, { 'Content-Type': 'application/json' });
const obj = {
name: 'david',
age: 12,
job: 'web'
}
res.end(JSON.stringify(obj))
} else {
// 否则,返回404页面
res.writeHead(200, { 'Content-Type': 'text/html' });
const path = __dirname + '/404.html'
fs.createReadStream(path, 'utf8').pipe(res)
}
}
var server = http.createServer(onRequest)
server.listen(3000)
console.log( 'Server started on localhost port 3000; http://localhost:3000' )
}
exports.startServer = startServer
11、web服务器part6重构路由代码
目录结构:
/----
app.js
server.js
route.js
handler.js
index.html
review.html
404.html
app.js
var server = require('./server')
var route = require('./route')
var handler = require('./handler')
/**[路由和渲染函数的映射] */
const handle = {};
handle['/'] = handler.home
handle['/home'] = handler.home
handle['/review'] = handler.review
handle['/api/v1/records'] = handler.api_records
server.startServer(route, handle)
server.js
const http = require('http')
function startServer (route, handle) {
var onRequest = function (request, response) {
route(handle, request.url, response)
}
var server = http.createServer(onRequest)
server.listen(3000)
console.log( 'Server started on localhost port 3000; http://localhost:3000' )
}
exports.startServer = startServer
route.js
const fs = require('fs')
function route (handle, pathname, response) {
const routeFn = handle[pathname]
if(typeof routeFn === 'function') {
routeFn(response)
} else {
response.writeHead(200, { 'Content-Type': 'text/html' });
fs.createReadStream(__dirname + '/404.html', 'utf8').pipe(response)
}
}
module.exports = route
handler.js
const fs = require('fs')
function home (response) {
response.writeHead(200, { 'Content-Type': 'text/html' });
fs.createReadStream( __dirname + '/index.html', 'utf8').pipe(response)
}
function review(response) {
response.writeHead(200, { 'Content-Type': 'text/html' });
fs.createReadStream(__dirname + '/review.html', 'utf8').pipe(response)
}
function api_records(response) {
response.writeHead(200, { 'Content-Type': 'application/json' });
const obj = {
name: 'david',
age: 12,
job: 'web'
}
response.end(JSON.stringify(obj))
}
module.exports = {
home,
review,
api_records
}
目前路由功能的结构分离成功。
12、web服务器part7使用get或者post发请求送数据
在上一节的基础上进行修改
server.js
const http = require('http')
const url = require('url')
const querystring = require('querystring')
function startServer (route, handle) {
var onRequest = function (request, response) {
const urlParse = url.parse(request.url, true)
let data = [];
request.on('error', function (err) {
console.log(err)
}).on('data', function (chunk) {
/**[第一种方法] */
// data += chunk
/**[第二种方法] */
data.push(chunk)
}).on('end', function () {
if(request.method.toLocaleUpperCase() === 'POST') {
data = Buffer.concat(data).toString();
route(handle, urlParse.pathname, response, querystring.parse(data))
} else {
route(handle, urlParse.pathname, response, urlParse.query)
}
})
}
var server = http.createServer(onRequest)
server.listen(3000)
console.log( 'Server started on localhost port 3000; http://localhost:3000' )
}
exports.startServer = startServer
route.js
const fs = require('fs')
function route (handle, pathname, response, params) {
const routeFn = handle[pathname]
if(typeof routeFn === 'function') {
routeFn(response, params)
} else {
response.writeHead(200, { 'Content-Type': 'text/html' });
fs.createReadStream(__dirname + '/404.html', 'utf8').pipe(response)
}
}
module.exports = route
handler.js
const fs = require('fs')
function home (response) {
response.writeHead(200, { 'Content-Type': 'text/html' });
fs.createReadStream( __dirname + '/index.html', 'utf8').pipe(response)
}
function review(response) {
response.writeHead(200, { 'Content-Type': 'text/html' });
fs.createReadStream(__dirname + '/review.html', 'utf8').pipe(response)
}
function api_records(response, params) {
response.writeHead(200, { 'Content-Type': 'application/json' });
response.end(JSON.stringify(params))
}
module.exports = {
home,
review,
api_records
}
index.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>nodejs</title>
</head>
<body>
<h1>hello nodejs</h1>
<form action="api/v1/records" method="POST">
name: <input type="text" name="name">
age: <input type="text" name="age">
<input type="submit" value="提交">
</form>
</body>
</html>
总结
1.模块的导入导出
2.事件的监听和触发
3.文件读写删
4.文件夹的增删
5.文件流的读取和写入
6.使用node搭建服务
7.web服务器返回JSON
8.web服务器返回html
9.web服务器代码模块化
10.添加路由
11.模块化路由代码
12.使用get、post接收发送数据