(TODO)NodeJS学习笔记

先应用,快速上手,不求甚解;后面再深入钻研。

感触:如果只是应用,其实现在NodeJS已经很成熟了,有非常多的现成模块可以使用,只要熟悉这些常用模块的常用api,就可以快速构建你的应用了。所以单纯从快速应用的角度出发,学习NodeJS就是使用这些模块的过程。

HTTP

如何创建HTTP服务器

通过http模块来实现:

1
2
const http = require("http")
const server = http.createServer((request, response) => {})

如何接收POST请求传递的数据

这个应该有很多好用的模块,不过我现在只尝试了原始的写法,这些模块等我后面不断去体验吧。

这里用到了querystring模块来解析http请求数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const http = require("http")
const querystring = require("querystring")

const server = http.createServer((request, response) => {
let postData = "";
// chuck是数据包的意思
// 请求数据是按chuck发送的,因此可能会发送多次,具体次数视数据大小、网速而定
request.on('data', (chuck) => {
postData += chuck;
})
request.on('end', () => {
let postObject = querystring.parse(postData)
response.setHeader("Access-Control-Allow-Origin", "*")
try {
let dataObject = eval("(" + postObject['content'] + ")")
response.write("Finished, I am response")
response.end()
} catch (exp) {
let message = "将客户端返回的数据转为JSON对象失败:" + exp.message;
response.write(message)
response.end()
}
})
})

如何上传文件

//TODO

如何解决跨域问题

前端经常是在自己本地用静态网页进行调试,直接访问本地html页面和js,然后发送请求到服务端。这存在跨域问题。

解决这个问题的方案,按照我之前做后端的经验,一般常用的有三种(随着技术的发展,现在可能不止3种,不过我没了解了):

  • 服务端设置响应头
  • 将本地文件放在和服务端同域名下进行访问
  • JSONP

针对服务端设置响应头,NodeJS里面可以通过response.setHeader(name, value)函数进行设置:

1
response.setHeader("Access-Control-Allow-Origin", "*")

客户端如何将数据传递上来

注意别忘记设置header头,特别是Content-Type属性,否则服务端解析数据会出问题。

另外传递上来的数据,记得处理成key1=value1&key2=value2的字符串格式。

原生JS发送Ajax的示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class Ajax {
create() {
let xmlHttp;
try {
//针对现在的主流浏览器 和IE7 以上版本的浏览器
xmlHttp = new XMLHttpRequest()
} catch (exp) {
try {
//针对IE6浏览器。
xmlHttp = new ActiveXObject('Msxml2.XMLHTTP')
} catch (exp) {
try {
//针对IE5.5之前的版本
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP')
} catch (exp) {
alert("您的浏览器版本太老了,不能使用ajax")
}
}
}
return xmlHttp;
}

send(options) {
if (!options || !options.url) {
alert("缺少ajax请求的参数,必须至少包含url参数")
return false;
}
options.method = options.method || 'GET'
let xmlHttp = this.create()
xmlHttp.open(options.method, options.url, true)
// 别忘了设置请求头了,否则后端处理会有问题
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
xmlHttp.send(options.data ? this.formatParams(options.data) : null)
xmlHttp.onreadystatechange = function () {
// status体现的是服务器对请求的反馈,而readystate表明客户端与客户的交互状态过程。
if (xmlHttp.readyState === 4) {
if (xmlHttp.status !== 200) {
alert("请求失败,状态码为:" + xmlHttp.status)
return false;
}
if (options.callback) {
options.callback(xmlHttp.responseText)
}
}
}
}
/**
* http请求实际传递的参数,需要处理成a=b&c=d的字符串格式
* @param {Object} params
*/
formatParams(params) {
let paramArr = []
Object.keys(params).forEach((key) => {
paramArr.push(key + "=" + params[key])
})
return paramArr.join('&')
}
}

文件操作

文件

1
2
3
4
5
6
7
8
9
10
11
12
const fs = require('fs')
const filePath = 'abc.txt';
// 读取文件
fs.readFileSync(filePath)
// 写入文件
fs.writeFileSync(filePath, 'this is data')
// 追加写入文件
fs.appendFileSync(filePath, 'this is data')
// 删除文件
fs.unlink(filePath)
// 判断文件是否存在
fs.exsistsSync(filePath)

文件夹

1
2
3
4
5
6
7
const fs = require('fs')
const dirPath = '/home/someone';
// 获取目录下的文件名列表
const fileNames = fs.readdirSync(dirPath)
// 判断是否是文件夹
const filePath = 'abc.txt';
fs.lstatSync(filePath).isDirectory()

写入文件

部署

代码热更新

通过supervisor包来实现:

1
2
npm install -g supervisor
supervisor app.js

启动服务后自动打开浏览器

通过child_process模块来实现,写在端口监听之后:

1
2
3
4
let prot = 3000
server.listen(port)
console.log("正在监听端口【" + port + "】")
childProcess.exec("start http://localhost:" + port + "/")

不过有了supervisor的热更新,通过child_process自动打开浏览器就没什么必要了。