NodeJs

一、什么是 NodeJs

NodeJs是在浏览器外运行V8 js 引擎,单线程非阻塞I/O事件驱动,适用于数据高并发,适合多请求,但不适合高运算,有权限读取操作系统的API,实现高性能Web服务器。

二、NodeJs 优缺点

优点:

  • 事件驱动,通过闭包实现客户端的生命周期
  • 单线程,高并发,多请求,异步处理机制,不阻塞(无需担心锁)
  • V8引擎速度快
  • 对于游戏来说,写一遍游戏逻辑,前后端通用

缺点:

  • 更新速度太快,容易出现版本不兼容
  • 不太成熟
  • 不支持进程和多线程操作

三、NodeJs 模块

1. fs内置模块:对文件和文件夹的操作模块

引入模块

const fs = require("fs");

文件夹

(1)新建文件夹

 ## 异步 ##
 
fs.mkdir(path[,options],callback);

//有三个参数,第一个参数是地址,就是你创建的文件夹存放的地址
//第二个参数不是必填的参数, options 参数可以是一个整数,用于指定文件的模式(权限与粘滞位)。 也可以是一个对象,其中 recursive 属性指定是否创建父目录。
//第三个参数是回调函数,参数就是err错误
 
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
  if (err) throw err;
});

异步都有回调函数,在node中,回调函数都有一个规范,错误优先的原则,回调函数的第一个参数都是err,表示是不是错误,默认的都是null,没有错误。

## 同步 ##

fs.mkdirSync(path[, options])
 
//同步和异步的区别就不多说了,在写法上的不用就是同步的方法没有回调函数,同步创建目录
//同步调用若是出错,都会终止执行,必须用try catch来捕获错误

try{
    let result=mkdirSync("./test2");
}catch(e){
    console.log(new Error("错误"));
}

(2)删除文件夹

 ## 异步 ##
 
fs.rmdir(path,callback);

//与新建类似,先是路径后面是回调函数

fs.rmdir("./test2",(err)=>{
    console.log(err);
})
 
//注意:fs.rmdir在删除文件夹的时候,不存在在的文件夹或者是不为空的文件不能删除

## 同步 ##

fs.rmdirSync(path);

(3)读取文件夹

 ## 异步 ##
 
fs.readdir(path[,options],callback);

//读取文件夹的时候,回调函数中会有两个参数,一个是错误,另一个就是读取的文件
//如果 options 是一个字符串,则指定字符编码。 如果 encoding 设为 'buffer',则返回的文件名是 Buffer,可以定义为 utf8。
 
fs.readdir("./test",(err,file)=>{
    console.log(err);
    console.log(file); // 文件夹中的文件,以数组的形式存放
})

## 同步 ##

fs.readdirSync(path[, options])
 
//如果 options 是一个字符串,则指定字符编码。 如果 encoding 设为 'buffer',则返回的文件名是 Buffer,可以定义为 utf8。

文件

(1)新建文件

fs.writeFile(file, data[, options], callback)
 
//创建一个新的文件,也就是说这个方法谢同一个文件是会覆盖的。

//以上是异步的写法,同步的写法与上面文件夹介绍的各个同步的方法没啥不一样,就是少了回调函数,返回值是undefined。

fs.appendFile("./file.txt",data,(err)=>{
    console.log(err);
})

//写入持续文件,就是writeFile换成了appendFile

(2)删除文件

fs.unlink(path,callback);
fs.unlink("./file.txt",(err)=>{
    console.log(err);
})

用的是unlink,删除一个不存在的文件会报错。

(3)读取文件

fs.readFile(file,callback);

callback回调函数中有两个参数,一个是err,另一个是data,读取的数据,一般data的格式都要改变,两种方法:

a.可以写成data.toString;
b.可以调用方法的时候多加一个参数,改变数值类型的(file,"utf8",callback);

2. path内置模块

引入模块

const path = require('path');

使用模块

path.resolve():返回当前模块的绝对地址(不包含模块名称)<=> __dirname
path.resolve([绝对路径],[相对路径]); =>拼接
path.resolve([绝对路径],[绝对路径]); =>只取第二个

path.resolve() VS __dirname
__dirname:当前模块所在的绝对路径(和模块在哪执行的没有关系)
path.resolve():当前模块中方法在哪个模块执行,那么对应的绝对路径就是执行模块的绝对路径

3. URL内置模块

引入模块

const url = require('url');

将一个url地址变成一个对象

const myURL = url.parse('https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash');

myURL.href : https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash
myURL.protocol : https:
myURL.username : user
myURL.password : pass
myURL.origin : https://sub.example.com:8080
myURL.host : sub.example.com:8080
myURL.hostname:sub.host.com
myURL.port : 8080
myURL.pathname : /p/a/t/h
myURL.search : query:string
myURL.hash : #hash

myURL.toString() 与myURL.href返回值相同
myURL.toJSON() 与myURL.href返回值相同

将对象(格式正确)转化成一个url地址

url.format(URL[, options]);

4.HTTP内置模块

引入模块

const http = require('http');

使用模块

let server = http.createServer(); //创建web服务
server.linten(); //监听端口
let port = 8686;
let handle = function(req,res){
    //当服务创建成功,并且客户端向当前服务器发送了请求,才会执行回调函数,并且发送一次请求,回调函数就会被触发执行一次
    //req:请求对象,包含了客户端请求的信息
    req.url //请求资源的路径地址及问好传参
    req.method //客户端的请求方式
    req.headers //请求头信息
    //...
    //res:响应对象,包含了一些属性和方法,可以让服务器端返回给客户端的内容
    res.write //基于这个方法,服务器端可以向客户端返回内容
    res.end //结束响应
    res.writeHead //重写响应头信息
    //...
};
http.createServer(handle).listen(port,()=>{
    //当服务创建成功,并且端口号也已经监听成功后,触发回调函数
    console.log(`server is success,listen on ${port}!`);
});

//Error: listen EADDRINUSE: address already in use :::80
//这种错误是由于端口号被占用了,我们需要修改端口号

5.queryString模块

引入模块

const querystring = require('querystring');
querystring.escape(str);//对给定的 str 进行 URL 编码
querystring.unescape(str);//对给定的 str 进行 URL 解码
querystring.stringify(obj[, sep[, eq[, options]]]);//将对象转化成字符串
querystring.parse(str[, sep[, eq[, options]]]);//将query字符串转化为对象

四、关于回调函数?

1. 什么是回调函数?

回调函数是指用一个函数作为参数传入另一个函数,这个函数会被在某个时机调用。

2. 什么是错误优先的回调函数?

错误优先(Error-first)的回调函数(Error-First Callback)用于同时返回错误和数据。第一个参数返回错误,并且验证它是否出错;其他参数返回数据。

fs.readFile(filePath, function(err, data){
    if (err){
        // 处理错误
        return console.log(err);
    }
    console.log(data);
});

3. 什么叫做回调地狱?

回调地狱是由嵌套的回调函数导致的。这样的机制会导致有些函数无法到达,并且很难维护。

4. 如何避免回调地狱?

  • 模块化:将回调函数转换为独立的函数
  • 使用流程控制库,例如[aync]
  • 使用Promise
  • 使用aync/await

5. 什么是Promise?

Promise可以帮助我们更好地处理异步操作。下面的实例中,100ms后会打印result字符串。catch用于错误处理。多个Promise可以链接起来。

new Promise((resolve, reject) =>{
    setTimeout(() =>{
        resolve('result');
    }, 100)
})
.then(console.log)
.catch(console.error);

五、NodeJs的适用场景

  • 实时应用:如在线聊天,实时通知推送等等(如socket.io)
  • 分布式应用:通过高效的并行I/O使用已有的数据
  • 工具类应用:海量的工具,小到前端压缩部署(如grunt),大到桌面图形界面应用程序
  • 游戏类应用:游戏领域对实时和并发有很高的要求(如网易的pomelo框架)
  • 利用稳定接口提升Web渲染能力
  • 前后端编程语言环境统一:前端开发人员可以非常快速地切入到服务器端的开发(如著名的纯Javascript全栈式MEAN架构)

六、相关小问

如何判断当前脚本是运行在浏览器还是node环境中?

<script>
    this === window ? console.log('browser') : console.log('node');
    /*
        判断global对象是否为window,
        为window在浏览器中运行
        不为window在node环境中运行
    */
</script>

【MARK】 文档以整理记录为主,如有错误,欢迎指出哟,大家一起来学习...

posted @ 2021-03-23 09:40  Red-Plum  阅读(18)  评论(0编辑  收藏  举报