nodejs基础一

一、node是什么?

1 目的

只有了解服务端才可更好配合服务端开发人员,前端+后端+运维部署

2 是什么

前端:html、js、css
后端:JAVA、PHP、Python、Rudy、Net、Nodejs

  • node不是一门语言
  • 不是库、不是框架
  • 是一个js运行环境,可以解析和执行js代码
  • 以前只有浏览器可以解析执行js代码
  • 现在的js可以脱离浏览器执行,归功于nodejs

浏览器里的js

  • EcmaScript 基本语法
  • BOM
  • DOM

nodejs中的js

  • 没有BOM和DOM
  • EcmaScript
  • 在node这个js执行环境中为js提供一些服务器级别操作的api,例如文件读写、网络服务的构建、网络通信、http服务器等处理

所以主要学的就是api

3 特性
  • 事件驱动
  • 非阻塞IO模型
  • 后面会学习
4 npm

npm是基于nodejs开发的包管理工具,世界上最大的开源库生态系统,绝大多数js相关的第三方包都存放在npm上,为了让开发人员更方便去下载和使用。

5 V8引擎
  • node构建于V8引擎之上。
  • 浏览器内分为渲染引擎和js执行引擎。
  • 代码只是具有特定格式的字符串,引擎可以认识他,帮助我们去解析和执行。
  • chrome的v8是公认的最快引擎

二、介绍node

1 nodejs能做什么
  • web服务器后台
  • 开发命令行工具【git(基于c)就是一个命令行工具,还有hexo(基于node)、npm(基于node)】
  • 对于前端开发工程师来说,接触node最多的是他的命令行工具

自己写的很少,主要是使用别人发的
webpack
gulb
npm

2 书本
  • 深入浅出nodejs(偏理论和底层,帮助理解原理)
  • nodejs权威指南(api讲解,没有实战,做api参考)
  • js标准参考教程alpha(阮一峰)
  • node入门(易于入门※)
  • 官网api文档
  • 中文文档(版本旧,可参考)
  • cnode社区(分享交流)
  • cnode新手入门
3 学到什么
  • b/s编程模型:任何服务端bs编程模型都是一样的,和语言无关;node只是作为一个工具
  • 模块化编程:Requirejs,Seajs
  • node中常用api
  • 异步编程
  • express开发框架
  • es6

三、基本编写

1 读写文件api
  • 在node中,采用es编码
  • 没有dom和bom,console不出来document和window
  • 和浏览器中的js不一样
  • 可以用来读取文件,浏览器中的js没有文件操作能力
 // fs是file-system的简写,就是文件系统的意思
// 在node中进行文件操作,就必须引入fs这个核心模块
// 在fs这个核心模块中,提供了文件操作相关的api
let fs = require('fs');
// 第一个参数是路径,第二个参数是回调函数
// 成功 data数据,error null
// 失败 data undefined,error数据
fs.readFile('hello.txt', function (err, data) {
    // 默认文件存储的都是二进制数据,看到的是二进制转为16进制
    // 需要使用tostring转成我们认识的字符
    console.log(data.toString());
})

输出为helle nodejs,成功。注意回调函数第一个参数是error,第二个是data,不要弄错顺序。还要注意路径。
增加一个错误处理

fs.readFile('hello.txt', function (err, data) {
    // 默认文件存储的都是二进制数据,看到的是二进制转为16进制
    // 需要使用tostring转成我们认识的字符
    if (err) {
        console.log('读取文件失败');
        return;
    }
    console.log(data.toString());
})

若要写入文件,代码如下:

let fs = require('fs');
// 成功 error是null,
// 失败,error是错误对象
fs.writeFile('hello.txt', 'write something', function (err) {
    console.log('error', err);
})

文件成功被改写, 错误处理如下

    if(err) {
        console.log('写入失败');
    } else {
        console.log('写入成功');
    }
2 简单的http
基础

可以使用node非常轻松构建一个node服务器
在node中,专门提供一个核心模块:http,该模块职责就是帮助创建编写服务器。

let http = require('http');
// 创建web服务器,server实例
let httpServer = http.createServer();
// 注册request请求事件,当客户端请求过来,自动触发request请求事件,然后执行回调函数
httpServer.on('request', function () {
    console.log('收到请求');
})
// 启动服务器
httpServer.listen(3000, function () {
    console.log('服务器启动成功,可以通过localhost:3000访问');
});

使用terminal执行该文件,随后在浏览器输入localhost:3000, 得到结果如图
在这里插入图片描述
因为代码中没有设置响应,所以浏览器一直处于转圈圈状态
在这里插入图片描述
CTRL+C就退出了

处理响应
let http = require('http');
// 创建web服务器,server实例
let httpServer = http.createServer();
// 注册request请求事件,当客户端请求过来,自动触发request请求事件,然后执行回调函数
// request处理函数需要接收两个参数
// Request请求对象,可以用来获取请求信息
// Response响应对象 可以用来给客户端发送响应信息
httpServer.on('request', function (request, response) {
    console.log('收到请求,路径为', request.url);
    // write可以用来给客户端发送响应数据
    // wirte可以使用多次,但是最后一定要end来结束响应,否则客户端会一直等待
    response.write('hello');
    response.write('nodejs');
    response.end(); // 很重要!!!!
})
// 启动服务器
httpServer.listen(3000, function () {
    console.log('服务器启动成功,可以通过localhost:3000访问');
});

此时访问localhost:3000得到
在这里插入图片描述
终端界面为
在这里插入图片描述

不同路径响应不同结果

例如/login, 响应 login,之前已经获取到url了,使用if-else即可。

let http = require('http');
let server = http.createServer();
server.on('request',function (req, res) {
    let url = req.url;
    console.log(url);
    // 使用write比较麻烦,推荐使用end直接发送响应数据
    // 根据不不同url响应
    // req.url获取到的是端口号之后的那一部分路径,都是以/开头
    if (url === '/') {
        res.end('index');
    } else if (url === '/login') {
        res.end('login');
    } else {
        res.end('404 not found');
    }
})
server.listen(3000, function () {
    console.log('服务器已启动与localhost:3000');
});
// 浏览器默认以80请求`

【注意】:响应内容只能是二进制数据或字符串!不能res.end(12),会报错。所以如果想返回对象的话需要转为json字符串。

server.on('request',function (req, res) {
    let url = req.url;
    console.log(url);
    // 使用write比较麻烦,推荐使用end直接发送响应数据
    // 根据不不同url响应
    // req.url获取到的是端口号之后的那一部分路径,都是以/开头
    if (url === '/') {
        res.end('index');
    } else if (url === '/login') {
        res.end('login');
    } else if (url === '/product') {
        let product = [
            {
                name: 'pencil',
                price: 1
            }, {
                name: 'flower',
                price: 20
            }
        ]
        res.end(JSON.stringify(product));
    }  else {
        res.end('404 not found');
    }
}) `

四、总结一

nodejs是什么

  • js运行时
  • 既不是语言,也不是框架,而是一个平台

nodejs中的js - 没有BOM、DOM

  • ES基本的js语言部分
  • 在node中为js提供了一些服务器级别的api,如文件操作能力、http服务能力

五、node中的js

  • EcmaScript
    • 没有DOM和BOM
  • 核心模块
  • 第三方库
  • 用户自定义模块
1 核心模块

Node为js提供了很多服务器级别的api,这些api绝大多数都被包装到了一个具名的核心模块中了,例如文件操作的fs核心模块,http服务构建的http,path路径操作模块,os操作系统信息获取模块。
如果说到这个模块是核心模块,就要知道如果想使用,比如引入:

let fs = require('fs');

在node官网可以查看核心模块。

let os = require('os');
// 获取机器信息
console.log(os.cpus());
console.log(os.totalmem());

let path = require('path');
// 处理路径
console.log(path.extname('c:/code/self/node/study/hello.txt'));
2 模块化编程
基本用法

node想执行多文件需用模块化编程
举例a文件和b文件
require是用来加载模块的:核心模块;自定义模块(js文件)
a文件:

console.log('a start');
// b 被解析并执行
// 相对路径的./不可省略,会当成核心模块
// 可以省略后缀名
require('./b');
console.log('a end');

b文件

console.log('b start');

在这里插入图片描述
可见require的意思就是加载并执行这部分代码, 按顺序

模块作用域

【注意】node中没有全局变量这个概念
模块作用域简单来说就是文件作用域,超出这个文件的都没用,外部访问不到内部,内部也访问不到外部,比如b和a中都有foo变量,互不影响,不会因为a require了b,变量名就冲突了。

既然是模块作用域,那如何让模块和模块之间进行通信,默认是封闭的,你可以加载我但是得不到我任何成员。有时候加载模块的目的不是简简单单执行一段代码,而是使用里面的一些成员,所以需要加载与导出

requie方法有两个作用:

  • 加载并执行某段代码
  • 拿到被加载文件模块导出的接口对象,在每个文件模块都提供了一个对象:exports(默认是一个空对象,需要做的就是将所有需要被外部访问的成员挂载到对象中,对象是动态的)

示例代码如下:
a:

let b = require('./b.js');
console.log(b);

b:

exports.foo = 'hello';

·在这里插入图片描述

六、Web服务开发

3 ip和端口号

所有联网的程序都需要进行网络通信。
计算机中只有一个物理网卡,而且同一局域网中,网卡的地址是唯一的。
网卡是通过唯一ip地址来进行定位的。
在这里插入图片描述
把我之前写的http程序运行起来,同一局域网的主机访问“172.20.10.7:3000“即可访问。
【注意】所有需要联网的应用程序都会占用一个端口号,我们浏览器去访问服务器也是有一个端口号的,浏览器自己开了一个闲的端口号。

  • 0-65536之间
  • 开发过程中不用默认的
  • 使用3000,5000没用好记的
  • 网站上线部署默认是80
  • 可以开启多个服务,但开启端口号不能重复
4 响应内容类型

如果不设置头,响应内容为中文时会乱码,设置如下:

let http = require('http');
let server = http.createServer();
server.on('request', function (req, res) {
    // 在服务端默认发送的数据是utf8编码内容
    // 但是浏览器不知道是utf8, 按当前操作系统默认方式解析
    // 中文操作系统是gbk
    // 告诉浏览器我给你发送的内容是什么编码的
    res.setHeader('Content-Type', 'text/plain; charset=utf-8');
    res.end('你好');

})
server.listen(3000, function () {
    console.log('服务启动');
})

如果响应内容是< p >hello< /p >,不加setHeader,浏览器收到后会将其作为html渲染。但是此时中文还是乱码,采用上述方式加setHeader解决乱码会发现浏览器不以html解析了,因为text/plain是普通文本如果发送的是html格式,需要用text/html;charset=utf-8
所以建议都要加上正确的contentType。

3 发送页面

之前的http服务器比较简单,接下来尝试返回html页面。在项目目录下新建resouce文件夹,在其中放一些文件,比如index.html, main.js, main.css, puppy.jpg, hello.txt。编写服务端文件如下:

let http = require('http');
const fs = require('fs');
let server = http.createServer();
server.on('request', function (req, res) {
    let url = req.url;
    // 想要返回html文件,但只能返回字符串,所以实际上是从文件中读取字符串返回
    if (url === '/') {
    // 结合fs
        fs.readFile('./resource/index.html', function (err, data) {
            if (err) {
                res.setHeader('Content-Type', 'text/plain; charset=utf-8');
                res.end('文件读取失败');
            } else {
                // data默认二进制数据 
                res.setHeader('Content-type', 'text/html; charset=utf-8');
                res.end(data);
            }
        })
    }
})
server.listen(3000, function () {
    console.log('server is running');
})

在这里插入图片描述
如果想要改变index.html,无需重启,因为再发请求就服务端程序会再获取一次文件内容,访问到的就是新的index.html,服务端程序无需重启。
如果想返回图片或css文件等,访问oschina,里面有标明不同资源对应的content-type,如下为增加图片。(图片无需指定编码)

let http = require('http');
const fs = require('fs');
let server = http.createServer();
server.on('request', function (req, res) {
    let url = req.url;
    // 想要返回html文件,但只能返回字符串,所以实际上是从文件中读取字符串返回
    if (url === '/') {
        fs.readFile('./resource/index.html', function (err, data) {
            if (err) {
                res.setHeader('Content-Type', 'text/plain; charset=utf-8');
                res.end('文件读取失败');
            } else {
                res.setHeader('Content-type', 'text/html; charset=utf-8');
                // data默认二进制数据,但在这里不用toString,因为已经指定utf-8了,除非想在后台打印
                res.end(data);
            }
        })
    }  else if (url === '/puppy') {
        fs.readFile('./resource/puppy.jpg', function (err, data) {
            if (err) {
                res.setHeader('Content-Type', 'text/plain; charset=utf-8');
                res.end('文件读取失败');
            } else {
                // 图片无需制定编码 
                res.setHeader('Content-type', 'image/jpeg');
                res.end(data);
            }
        })
    }
})
server.listen(3000, function () {
    console.log('server is running');
})

七、总结

1 模块系统
  • 在node中没有全局作用域的概念
  • 在node中可以通过require来加载和执行多个js脚本文件
  • require加载只是执行其中的代码,文件和文件之间由于模块作用域,所以不会有污染的问题
    • 模块是完全封闭的
    • 外部无法访问内部
    • 内部也无法访问外部
  • 模块作用域固然带来一些好处,可以加载多个js文件,可以完全不避免变量命名该冲突
  • 但是某些情况下模块与模块之间是需要通信的
  • 在每个模块中都提供了一个exports对象
  • 该对象默认是一个空对象
  • 你要做的就是把需要被外部访问使用的成员手动挂载到exports接口对象中
  • 然后谁要require这个模块,谁就可以得到模块内部的exports接口对象
2 核心模块
  • 核心模块是由node提供的一个个具名模块,他们都有自己特殊的名称标识
  • 所有核心模块使用的时候都必须用require手动加载
3 http
  • require
  • 端口号
    • ip地址定位计算机,端口号定位具体应用程序
  • Content-Type
    • 服务器最好把每次响应数据是什么内容都告诉客户端,而且要正确告诉
    • 不同资源对应的饿Content-Type是不一样的
    • 对于文本类型的数据,最好都加上编码,目的是为了防止中文解析乱码的问题
  • 通过网络发送文件
    • 发送的并不是文件,本质上来说是发送文件的内容
    • 当浏览器收到服务器响应内容之后,就会根据你的Content-Type进行对应的解析处理
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值