- 支持更多特性
- 不缓冲响应和请求
- 处理流相关
一些概念
- 什么是同步/异步
- 什么是回调
- 什么是IO
- 什么是阻塞/非阻塞
- 什么是事件
- 什么是事件驱动
- 什么是基于事件驱动的回调
什么是同步/异步
同步
举个例子: 打电话预定餐馆有没有位置,餐馆说查询一下,这时你等待 餐馆的查询结果,然后挂电话,这就是一个同步的例子
打电话-等待查询结果-挂电话
同步就是执行任务,后一个任务等待前一个任务执行完成再执行,程序的 执行顺序与任务的排列顺序是一致的
a
var i=0;
while(true){
i++;
}
console.log(i)
上面是一个死循环,console.log永远也不会执行
异步
也是打电话的例子: 餐馆说“我查一下”,然后就挂电话了,找到结果 再打电话通知你 这里老板是通过回电话这种方式回调 打电话-留号码-查结果-回电话
任务的执行顺序与任务的排列顺序不是一致的,任务通过回调控制流程
javascript最基础的异步函数是:
- setTimeout
- setInterval
var c=0;
function printIt(){
console.log(c)
}
function plus(callback){
setTimeout(function(){
c+=1;
callback();
},1000)
}
plus(printIt);
console.log(111);
什么是回调
JavaScript 语言对异步编程的实现,就是回调函数。所谓回调函数,就是把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数。
callback.js
function callback(something){
console.log(something);
}
function we(callback, something){
setTimeout(function(){
callback(something);
}, 300);
}
什么是IO
磁盘读写或网络通信(统称为 I/O 操作)通常要耗费较长的时间
基本用法
处理GET请求
http模块主要用于搭建HTTP服务。使用Node搭建HTTP服务器非常简单。
一个http服务器
var http = require('http');
var app = http.createServer(function (request, response){
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
});
app.listen(8080, '127.0.0.1');
console.log('Server running on port 8080.');
-
调用http模块的createServer方法,创造一个服务器实例。
-
ceateServer方法接受一个函数作为参数,该函数的request参数是一个对象,表示客户端的HTTP请求;response参数也是一个对象,表示服务器端的HTTP回应。
-
response.writeHead方法用来写入HTTP回应的头信息;
-
listen(8080)表示启动服务器实例,监听本机的8080端口。
response.end方法用来写入HTTP回应的具体内容,以及回应完成后关闭本次对话。
返回文件
var http = require('http');
var fs = require('fs');
var app = http.createServer(function (request, response){
fs.readFile('index.html', function readData(err, data) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end(data);
});
});
app.listen(8080, '127.0.0.1');
console.log('Server running on port 8080.');
根据不同网址的请求,显示不同的内容
var http = require("http");
http.createServer(function(req, res) {
// 主页
if (req.url == "/") {
res.writeHead(200, { "Content-Type": "text/html" });
res.end("Welcome to the homepage!");
}
// About页面
else if (req.url == "/about") {
res.writeHead(200, { "Content-Type": "text/html" });
res.end("Welcome to the about page!");
}
// 404错误
else {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("404 error! File not found.");
}
}).listen(8080, "localhost");
回调函数的req(request)对象,拥有以下属性。
- url:发出请求的网址。
- method:HTTP请求的方法。
- headers:HTTP请求的所有HTTP头信息。
处理POST请求
当客户端采用POST方法发送数据时,服务器端可以对data和end两个事件,设立监听函数。
var http = require('http');
http.createServer(function (req, res) {
var content = "";
req.on('data', function (chunk) {
content += chunk;
});
req.on('end', function () {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("You've sent: " + content);
res.end();
});
}).listen(8080);
data事件会在数据接收过程中,每收到一段数据就触发一次,接收到的数据被传入回调函数。end事件则是在所有数据接收完成后触发。
使用postman做测试
发出请求
request()
request方法用于发出HTTP请求,它的使用格式如下。
http.request(options[, callback])
options对象可以设置如下属性:
- host:HTTP请求所发往的域名或者IP地址,默认是localhost。
- port:远程服务器的端口,默认是80。
- method:指定HTTP请求的方法,格式为字符串,默认为GET。
- path:指定HTTP请求的路径,默认为根路径(/)。可以在这个属性里面,指定查询字符串,比如/index.html?page=12。如果这个属性里面包含非法字符(比如空格),就会抛出一个错误。
- headers:一个对象,包含了HTTP请求的头信息。。
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
var options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write(postData);
req.end();
get
get方法用于发出get请求。
function getTestPersonaLoginCredentials(callback) {
return http.get({
host: 'personatestuser.org',
path: '/email'
}, function(response) {
var body = '';
response.on('data', function(d) {
body += d;
});
response.on('end', function() {
var parsed = JSON.parse(body);
callback({
email: parsed.email,
password: parsed.pass
});
});
});
}
注意,上面代码中,req.end() 必须被调用,即使没有在请求体内写入任何数据,也必须调用。因为这表示已经完成HTTP请求。
发送过程的任何错误(DNS错误、TCP错误、HTTP解析错误),都会在request对象上触发error事件。