异步和回调
- JavaScript中有一些居家旅行必备的异步函数, 例如 setInterval, setTimeout, forEach 以及最常见的事件绑定.
- 异步函数用于指派 (assign) 一些延迟执行的任务, 这些任务也就是回调函数
- 回调函数只有在特定的条件满足后, 才会被调用.
- 也就是说异步函数仅仅是在内存中创建了回调函数的执行环境就结束, 解释器并不会等待回调函数的执行, 而是立即执行后面的语句. 而回调函数的执行, 则是由条件触发的.
nodejs 初始化一个服务器
- 在nodejs中, 我们通过 http.creatServer(requestListener) 创建一个server实例, requestListener是请求的处理函数.
- requestListener 接收两个默认的位置参数, 第一个为http请求, 第二个为http响应.
let http = require('http')
let fs = require('fs')
let url = require('url')
// 指定端口
port = 8888
let server = http.createServer( (request, response) => {
})
server.listen(port)
- 在 nodejs 中, 为了获得请求体, 我们需要监听请求的 'data' 事件, 将每次获得的数据拼接起来. 然后在请求接收完毕后, 也就是请求的 'end' 事件的回调函数中来定义对数据的处理和服务器的响应.
- 以下代码用于实现这个需求:
let requestBodyString = ''
request.on('data', (chunk) => {
requestBodyString += chunk
})
request.on('end', () => {
let requestBody = JSON.parse(requestBodyString)
response.statusCode = 200
response.end(JSON.stringify(requestBody))
})
关闭请求和响应
- 关闭请求和响应的必要性:
- 根据TCP协议, 每一次发起请求或响应后都需要结束, 才能取消对接socket的阻塞状态, 对接的socket才能获取到数据.
- 为了动态地响应请求, 我们需要在请求结束的事件回调函数中解析数据, 这些任务就是异步的.
异步的陷阱:
- 在上面示例代码的基础上, 如果我们在请求的end事件处理函数下面加上 response.end() 语句, 那么等到回调函数中的代码执行的时候, 针对请求的响应早已经被提前结束了, 回调函数中的代码仍然会执行, 代码也不会报错, 但是其中的响应将永远不会抵达.
let requestBodyString = ''
request.on('data', (chunk) => {
requestBodyString += chunk
})
request.on('end', () => {
let requestBody = JSON.parse(requestBodyString)
response.statusCode = 200
response.end(JSON.stringify(requestBody))
})
// 在request对象的end事件绑定完成后立即执行, 不会等待end事件的回调函数.
response.end()