我们写个表单,来看下基于node.js的前后端交互。
先说明要做的事情: 表单中输入数据提交后传给服务端,服务端收到HTTP请求后响应,传送数据给客户端,客户端输出显示(这里不写模板渲染了)
首先我们写个html文件建立一个表单,程序如下:
home.html
主页
直接使用button可能会出错,单击按钮自动刷新。
见讨论:http://bbs.csdn.net/topics/390307663
之后我们写服务端程序,在浏览器输入url后返回这个页面:
server.js
var http = require('http')
var fs = require('fs')
var server = new http.Server()
function sendfile( res, abspath, data ) {
res.writeHead(
200,
{'content-type': 'text/html'}
)
res.end( data )
}
function serverStatic(res,abspath) {
fs.readFile( abspath, function (err,data){
sendfile( res, abspath, data )
})
}
server.on( 'request', function (req, res) {
console.log('-----接收到请求-----')
serverStatic(res,'./home.html')
})
server.listen(2500)
下面对上面的程序做出说明:
首先我们需要导入http模块和fs模块。fs模块是用来提供文件系统相关功能的。
先建立一个Http.Server类实例,用该实例进行服务端操作。看下官方文档
http://nodejs.cn/api/http.html#http_class_http_server
官网第一句:该类继承自 net.Server,且具有以下额外的事件:
这里我们用到的是request事件,对于request事件,提供一个监听函数,这个监听函数有两个参数
request,response。不要把监听函数里的request对象和request事件混为一谈,request事件里的request是事件名称
request事件的监听函数中的request对象是http.IncomingMessage实例,http.IncomingMessage是个可读流,数据从外部流到node,
你可以读取里面的数据,可读流可以自动读取(on或者pipe),也可以手动读取(read)。
request事件的监听函数中的response对象是http.ServerPonse实例,用官网里的话说http.ServerPons这个类实现了(而不是继承自)可写流 接口。
总结一下:在node是服务端的时候,req是从客户端发起的,是可读流,res是从node响应的,是可写流。
之后我们再看下文档对http.ServerResponse 类的描述
该对象在 HTTP 服务器内部被创建。 它作为第二个参数被传入 'request' 事件。
它作为第二个参数被传入‘request’事件也就是说它被作为‘request’事件的监听函数的第二个参数传入。server.on( 'request', function (req, res) {} )代码中的res就是http.ServerResponse类实例。
http.ServerResponse类有个方法,end方法,如下:
下面我们看使用fs模块获取文件内容
我们上管网看下如何使用fs模块读取硬盘文件
http://nodejs.cn/api/fs.html#fs_fs_readfile_path_options_callback
fs.readFile( abspath [,options], callback )有三个参数,其中第二个参数options参数可选, 第三个参数callback是回调函数
第一个参数是文件名或者文件描述符,可以传入string,url,buffer,interager类型的值给path,这里我们选的是绝对路径..
回调函数有两个参数,回调有两个参数 (err, data),其中 data 是文件的内容。
这样使用fs.readFile可以获取文件内容了。然后我们还要将文件内容作为响应的数据响应。因此需要这句res.end( data ),data就是文件内容。
总结一下代码思路,fs获取home.html文件内容data,之后响应以data返回.
至此输入url获取页面已经成功了,之后要做的就是发送POST请求,服务端获取请求的数据
我们获取点击按钮获取input的value的值将其发送给服务端,发起请求直接使用xhr对象即可,详细的见js高级教程
直接给出代码:
var button = document.getElementById("login")
var xhr = new XMLHttpRequest()
var handler = function(event) {//点击后获取input的值并发送
var value = document.getElementById("inputName").value
// console.log(value)
xhr.open('post','/',true)//启动请求,url可以是相对于执行代码的当前页面
xhr.send( value )
}
button.addEventListener('click', handler )
server.on( 'request', function (req, res) {
console.log('-----接收到请求-----')
//res.end('hello')
serverStatic(res,'./home.html')
if( req.method=='POST' ){
//console.log(req)
console.log(req.rawHeaders)
var data = ""
req.on("data",function(chunk){
data += chunk
})
req.on("end",function(){
// console.log(data)
res.writeHead(
200,{'Content-Type':'text/plain'}
)
res.end('响应数据: '+data)
})
}
})
对上面代码做些说明,官网有下面的话:
查看英文版 / 参与翻译
IncomingMessage
对象由 http.Server
或 http.ClientRequest
创建,并作为第一个参数分别递给 'request'
和 'response'
事件。 它可以用来访问响应状态、消息头、以及数据。
它实现了 可读流 接口,还有以下额外的事件、方法、以及属性
注意最后一句: 它实现了 可读流 接口,还有以下额外的事件、方法、以及属性
查看英文版 / 参与翻译
chunk
Buffer
。 对于对象模式的可读流,这可以是除 null
以外的任意类型 JavaScript 值。 'data'
事件会在流将数据传递给消费者时触发。当流转换到 flowing 模式时会触发该事件。调用 readable.pipe()
, readable.resume()
方法,或为 'data'
事件添加回调可以将流转换到 flowing 模式。 'data'
事件也会在调用 readable.read()
方法并有数据返回时触发。
在没有明确暂停的流上添加 'data'
事件监听会将流转换为 flowing 模式。 数据会在可用时尽快传递给下个流程。
如果调用 readable.setEncoding()
方法明确为流指定了默认编码,回调函数将接收到一个字符串,否则接收到的数据将是一个 Buffer
实例。
const readable = getReadableStreamSomehow();
readable.on('data', (chunk) => {
console.log(`Received ${chunk.length} bytes of data.`);
});
'data'
事件会在流将数据传递给消费者时触发,对应的监听函数中的chunk是数据片段,因为消息是一段一段发送的。消息发送完成后,流中无数据可供消费,触发end事件
查看英文版 / 参与翻译
'end'
事件将在流中再没有数据可供消费时触发。
最后一步,客户端收到需要响应后输出,在home.html中添加如下代码即可:
xhr.onreadystatechange = function () {
if( xhr.readyState==4 ){//已经接收全部响应数据
if( (xhr.status>=200&&xhr.status<300) || xhr.status==304 ){
console.log( '-----请求并响应成功------' )
console.log(xhr.responseText)
console.log( '-----请求并响应成功------' )
}else{
console.log( "请求未成功: " + xhr.status )
}
}
}
xhr.onreadystatechange()
home.html
主页
server.js
var http = require('http')
var fs = require('fs')
var server = new http.Server()
function sendfile( res, abspath, data ) {
res.writeHead(
200,
{'content-type': 'text/html'}
)
res.end( data )
}
function serverStatic(res,abspath) {
fs.readFile( abspath, function (err,data){
sendfile( res, abspath, data )
})
}
server.on( 'request', function (req, res) {
console.log('-----接收到请求-----')
//res.end('hello')
serverStatic(res,'./home.html')
if( req.method=='POST' ){
//console.log(req)
console.log(req.rawHeaders)
var data = ""
req.on("data",function(chunk){
data += chunk
})
req.on("end",function(){
// console.log(data)
res.writeHead(
200,{'Content-Type':'text/plain'}
)
res.end('响应数据: '+data)
})
}
})
server.listen(2500)
参考 js高级教程
node.js官网
流:https://segmentfault.com/a/1190000000519006?share_user=1030000004603185