热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

快速入门nodejs学习

nodejs学习简介nodejs是一个事件驱动IO服务端的JavaScript环境,没有DOM,浏览器之类的东西。Chrome的V8引擎是用C++写的,执行JS速度快。powers




nodejs学习


简介


  • nodejs是一个事件驱动I/O服务端的Javascript环境,没有DOM,浏览器之类的东西。
  • Chrome的V8引擎是用C++写的,执行JS速度快。
  • powershell是功能更强的cmd。

创建服务

创建一个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的事件(一)


  • 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的事件(二)


  • nodejs里面所有异步的io操作,都会在完成时,发送一个事件到事件队列。
  • events这个模块只有一个对象events.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");

Buffer(缓冲区/缓存)


  • nodejs的开发语言就是js,Javascript语言自身只有字符串数据类型,没有二进制数据类型。
  • nodejs有时会操作一些文件,或者说是tcp流之类的东西,那就必须操作二进制数据。
  • 在nodejs中,有一个buffer类,它用来创建一个专门存放二进制数据的缓存区。
  • buffer类是随nodejs的核心一起安装的,直接引入即可,这些原始数据是存储在buffer类的实例里,一个buffer类相当于是一个整数的数组,它相当于是划出了一块自己的内存空间。
  • buffer类的实例用于表示 编码字符 的序列,它支持utf-8,base64,ascii等。

1.创建一个Buffer类:

Buffer.alloc,它是返回一个指定大小的Buffer实例。

//创建一个长度为10,并且用0填充的buffer
const buf1 = Buffer.alloc(10);

2..write()向buffer实例中写入内容:

3..toString(),从缓冲区中读取数据。下面是其中的参数:


  • 默认编码是utf8
  • start,开始位置
  • end,结束位置

//创建一个长度为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流


  • Stream流(简单理解就是一个在线读取的资源),是一个抽象的接口,在nodejs当中,很多方法、对象。它们都实现了这个接口。

    例如:之前创建一个服务,向服务器发起一个请求,request对象,它其实就是个Stream。

  • 在nodejs当中,Stream有四种流类型:


    • Readable —可读操作
    • Writeable —可写操作
    • Duple—可读可写操作
    • Transform —操作被写入数据,然后读出结果
  • 所有的Stream对象,都是EventEmitter的实例,常用的事件:


    • data 当有数据可读取时触发
    • end 没有更多的数据可读取时触发
    • error 在接收和写入过程中,发生错误时触发
    • finish 所有的数据读取完成时触发

虽然是从流中去读取文件,但是依然是在操作文件,所有还是要用到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("执行完成了!");

  • nodejs中的管道流,提供了一个从输出流到输入流的机制(就像水龙头一样,从一个地方流入到了另一个地方),就是从一个流当中获取数据,并传递到另一个流当中,主要用到了,.pipe()方法。

管道流示例

var fs = require('fs');//创建一个可读流,createReadStreamvar readStream = fs.createReadStream("writedemo.txt");//创建一个可以写入的流var writeStream = fs.createWriteStream("pipedemo.txt");//管道流操作readStream.pipe(writeStream);console.log("执行完毕!");

  • 链式流就是从一个输出流中读取数据,创建了多个流来操作这个输出流的数据的机制。一般用来操作管道流,常见的例子就是压缩和解压缩(zlib)。

链式流示例

压缩:

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提供了两个对象:


    • exports—它是模块公开的接口
    • require—用来获取外部的模块的接口
  • 创建模块的两种方式


    • 只公开一个方法(一般公开的方法名和它所在的模块是同名的):exports.方法名 = function(){ … }
    • 把整个模块都全部公开出来:moudle.exports = function(){ … }

get请求


  • 获得get请求的内容,它的内容是在URL的?号之后的部分(例如:?a=1&b=2&c=3):


    • util(nodejs的工具对象,有许多许多的方法)
    • util.inspect,用来把对象转换为字符串
    • url,是nodejs的url模块
    • url.parse,解析url请求之类的东西

    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端口服务已经打开');


post请求


  • 要用到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端口服务已经打开');


express框架


  • 一个简洁的nodejs web应用框架,它提供一些功能,可以帮助你快速地搭建一个完整的网站。
  • 核心特性:
    • 可以使用中间件来响应http请求
    • 可以设置一些简单的路由:(手动)
  • 安装 Express,npm install express --save(–save意思是安装在你的开发目录,而不是全局安装。)

使用express创建一个服务

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已经启动");});

express路由


  • 简单的路由,就是一个最简单的spa单页应用

express创建路由

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已经启动");});

静态目录


  • Express有内置的中间件的设置,可以用来设置静态目录,express.static(),可以让我们通过http的方式,来访问静态文件。
  • 它的效果和我们把文件放在phpstudy服务器上面的效果是一样的。

var express = require('express');var app = express();//设置静态目录app.use(express.static('staticDev'));app.listen(5472,function(){ console.log('5472,静态目录,已经启动');});


推荐阅读
author-avatar
Smile--麦芽
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有