创建一个http服务由以下3个部分构成:
引入模块,require,把这个模块用一个变量接收。
var xx = require(“http”);
创建服务器
处理请求与响应
//创建一个服务
//引入一个模块,把这个模块保存在 _httpv变量当中
var _httpv = require("http");
// console.log(_httpv.createServer)
_httpv.createServer(function(request,response){
//http头部的信息
//状态码200
//内容的类型:text/plain(纯文本), text/html(html形式)..., xml
response.writeHead(200,{'Content-Type':'text/html'});
//向客户端发送数据
response.end("hello nodejs");
}).listen(8080);
//控制台打印信息
console.log("8080已经创建!")
创建各种服务,通过各种接口,提供各种数据。
异步编程的直接体现:异步回调的直接体现:异步回调
1.开发语言是js,js本身就是事件驱动的,是异步的;
2.因为是js的,所以是单线程的,现在是多线程的。
通过异步来处理大并发:
阻塞的例子:.readFileSync(文件名)是同步读取文件
// 通过异步来处理大并发(一个阻塞的例子)
//在nodejs中操作文件使用的是fs模块
var _fs = require("fs");
// console.log(_fs.readSync)
//.readFileSync是同步读取文件
var _data = _fs.readFileSync('New Collection.postman_collection.json');
//直接输出会是个二进制的流,此时可以采用toString方法
// console.log(_data);
console.log(_data.toString());
console.log('js已经执行结束');
/*
这种操作在本质上已经形成了阻塞
*/
非阻塞的例子:.readFile()基于回调的异步读取文件
//基于回调的非阻塞的文件读取
var _fs = require('fs');
//第一个参数是要读取的文件名
//第二个参数是处理读取到的文件的内容的回调函数
_fs.readFile('New Collection.postman_collection.json',function(err,_data)){
if(err) return err;
console.log(_data.toString());
};
console.log("----------");
console.log("js已经执行结束!");
/*
我们不需要等待文件读取完成,可以在读取文件的时候同时去执行下面的代码,提高了js的性能。
*/
回调的例子:回调的函数一般是作为最后一个形参出现。
实际工作中,最具体的应用就是jq的$.ajax()。
nodejs是一个单进程单线程的应用程序,由于V8引擎提供了异步执行回调的接口,通过这些接口处理大的并发请求,性能很高。
基本上nodejs所有的事件机制,都是基于设计模式中的“观察者模式”来实现的。
nodejs使用事件驱动的模型:每当接收到一个请求,就把它关掉进行处理,当这个请求完成,就把它放到处理队列当中,最后把结果返回给用户。
由于nodejs的服务一直都是处理接收请求,但不等待任何的读写操作,所以性能很高,这也叫“非阻塞式的I/O或是事件驱动I/O"。
nodejs的事件是使用 events 模块(require(“events”)),通过实例化( var event = new xx.EventEmitter)它里面的 EventEmitter 类来绑定和监听事件。
绑定事件:event.on(…)
监听事件:event.emit(…)
node中的js,依然还是那个js,依然是从上到下一行一行的读取的解释型的脚本语言。编写时依然要注意顺序。
/*
nodejs 事件
*/
var _events = require("events");
//EventEmitter的一个实例
var _EventEmitter = new _events.EventEmitter();
//这里的事件名,完全不同于浏览器的各种事件,这里完全就只是一个标识,它其实是绑定了一个回调函数。
_EventEmitter.on("xx123",function(){
console.log("xx123事件已经被触发");
//事件的嵌套
_EventEmitter.emit("xx456");
});
_EventEmitter.on("xx456",xx456fn);
function xx456fn(){
console.log("xx456事件已经被触发");
}
//触发一个事件
_EventEmitter.emit("xx123");
console.log(_EventEmitter);
//第一个nodejs的事件的例子
var _EventEmitter = require("events").EventEmitter;
var _event = new _EventEmitter();
_event.on("timeout",function(){
console.log("timeout 事件被触发!");
})
setTimeout(function(){
_event.emit("timeout");
},2000)
console.log(_event);
EventEmitter,它的每个事件都是由:
1.事件名,是一个字符串
2.若干个参数
可以在一个实例上,通过on绑定多个事件,然后通过同一个.emit()方法触发并传参。如下实例:
//可以在一个实例上,通过on绑定多个事件,然后通过同一个.emit()方法触发并传参
var _EventEmitter = require("events").EventEmitter;
var _event = new _EventEmitter();
_event.on("xx1",function(arg1,arg2){
console.log("xx11111",arg1);
})
_event.on("xx1",function(arg1,arg2){
console.log("xx22222",arg2);
})
_event.emit("xx1","这是1111","这是2222");
1.创建一个Buffer类:
Buffer.alloc,它是返回一个指定大小的Buffer实例。
//创建一个长度为10,并且用0填充的buffer
const buf1 = Buffer.alloc(10);
2..write()
向buffer实例中写入内容:
3..toString()
,从缓冲区中读取数据。下面是其中的参数:
//创建一个长度为10,并且用0填充的bufferconst buf1 = Buffer.alloc(256);let text = buf1.write("我是秃头小框");console.log(buf1);console.log("写入的字节数:"+text);console.log(buf1.toString());console.log(buf1.toString('utf8',0,3));
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mMGOonTk-1622692398527)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210527151818913.png)]
例子:
//批量输出26个字母const buf = Buffer.alloc(26);for(var i=0;i<26;i++){ buf[i] = 97 + i;}console.log(buf);console.log(buf.toString());console.log(buf.toString("ascii"));
4.将Buffer转换为JSON对象:
buf.toJSON(),它的返回值是一个json对象。
调用Buffer.from(),它是返回一个被array的值,初始化之后的新的Buffer实例。
array之中的元素只能是数字,否则会被0覆盖。
//0x加数字表示是16进制的数字const buf1 = Buffer.from([0x1,0x2,0x3]);console.log(buf1);
5.JSON.stringify()
,用于将Javascript值(对象/数组)转化为一个JSON字符串。
//0x加数字表示是16进制的数字const buf1 = Buffer.from([0x1,0x2,0x3]);const _json = JSON.stringify(buf1);console.log(buf1);console.log(_json);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gw8YWj7R-1622692398534)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20210527154913845.png)]
6.JSON.parse()
是将json字符串,转为json对象。
//0x加数字表示是16进制的数字const buf1 = Buffer.from([0x1,0x2,0x3]);const _json = JSON.stringify(buf1);console.log(buf1);console.log(typeof _json);//字符串类型console.log(typeof JSON.parse(_json));//对象类型console.log(typeof JSON.parse(_json).data);
Stream流(简单理解就是一个在线读取的资源),是一个抽象的接口,在nodejs当中,很多方法、对象。它们都实现了这个接口。
例如:之前创建一个服务,向服务器发起一个请求,request对象,它其实就是个Stream。
在nodejs当中,Stream有四种流类型:
所有的Stream对象,都是EventEmitter的实例,常用的事件:
虽然是从流中去读取文件,但是依然是在操作文件,所有还是要用到nodejs当中的fs模块。
var fs = require('fs');var data = '';//创建一个可读流var readStream = fs.createReadStream("Words.txt");//设置可读流的编码格式,utf8readStream.setEncoding('utf8');//处理流的事件,data,error,endreadStream.on('data',function(_d){ data += _d;});readStream.on('end',function(){ console.log(data);});console.log("读取完毕!");
var fs = require('fs');var data = '我是秃头小框,我喜欢这个世界!';//创建一个可以写入的流var writeStream = fs.createWriteStream("writedemo.txt");//设置编码writeStream.write(data,'utf8');//标记文件末尾writeStream.end();writeStream.on('finish',function(){ console.log("写入完成!");});console.log("执行完成了!");
.pipe()
方法。var fs = require('fs');//创建一个可读流,createReadStreamvar readStream = fs.createReadStream("writedemo.txt");//创建一个可以写入的流var writeStream = fs.createWriteStream("pipedemo.txt");//管道流操作readStream.pipe(writeStream);console.log("执行完毕!");
压缩:
var fs = require('fs');var zlib = require('zlib');//压缩文件fs.createReadStream("writedemo.txt") .pipe(zlib.createGzip()) .pipe(fs.createWriteStream("writedemo.txt.gz"));console.log("压缩完了!");
解压缩:
var fs = require('fs');var zlib = require('zlib');//解压缩文件fs.createReadStream("writedemo.txt.gz") .pipe(zlib.createGunzip()) .pipe(fs.createWriteStream("Gunzipwritedemo.txt"));console.log("解压缩完了!");
模块是nodejs应用程序的基本组成部分。
文件和模块是一一对应的,一个是nodejs的文件,就是一个模块。
nodejs提供了两个对象:
创建模块的两种方式
获得get请求的内容,它的内容是在URL的?号之后的部分(例如:?a=1&b=2&c=3):
js//get请求var _http = require('http');var _util = require('util');var _url = require('url');_http.createServer(function(req,res){ res.writeHead(200,{ 'Content-Type':'text/plain;charset=utf-8' }); var _param = _url.parse(req.url,true).query; console.log(_param); // res.end('xx123'); //end方法只能向页面发送字符串 //res.end(_url.parse(req._url));error:_url.parse(req._url)是一个对象 // res.end(_util.inspect(_url.parse(req._url))); res.write("姓名:"+_param.name); res.write("\n"); res.write("年龄:"+_param.age); res.end();}).listen(5642);console.log('5642端口服务已经打开');
要用到querystring,用来解析url的,querystring.parse()
,用于将一个字符串转换为对象。
//post请求var _http = require('http');var querystring = require('querystring');var _formHtml = '' + '姓名:
'+ '年龄:
'+ '' + '';_http.createServer(function(req,res){ var body = ''; req.on('data',function(_d){ body += _d; }); req.on('end',function(){ body = querystring.parse(body); res.writeHead(200,{ 'Content-Type':'text/html;charset=utf-8' }); if(body.name){ res.write('姓名:' + body.name); res.write('
'); res.write('年龄:' + body.age); } else{ res.write(_formHtml); } res.end(); });}).listen(5642);console.log('5642端口服务已经打开');
var express = require('express');// console.log(express);var app = express();//'/',就是根路径app.get('/',function(req,res){ res.send('第一个express例子,创建一个服务');});app.listen(5472,function(){ console.log("5472已经启动");});
var express = require('express');// console.log(express);var app = express();//'/',就是根路径app.get('/',function(req,res){ res.send('1
a页面
b页面');});app.get('/a',function(req,res){ res.send('2
a1页面');});app.get('/a/a1',function(req,res){ res.send('2.1
回到首页');});app.get('/b',function(req,res){ res.send('1.1
b1页面');});app.get('/b/b1',function(req,res){ res.send('1.2回到首页');});app.listen(5472,function(){ console.log("5472已经启动");});
var express = require('express');var app = express();//设置静态目录app.use(express.static('staticDev'));app.listen(5472,function(){ console.log('5472,静态目录,已经启动');});