【nodejs】基础介绍

Node是什么?

官网定义:Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine

node 是一个JavaScript运行时(runtime),所谓运行时就可以想象成一个编程语言的运行环境。

这个运行环境包括了运行代码需要的编译器(解释器)以及操作系统的底层支持等。

 

Node特点是什么?

单线程:单线程是Node.js保持轻量级和高性能的关键,这里的单线程是主线程为‘单线程’, 所有阻塞的部分交给一个线程池处理,然后主线程通过一个队列跟线程池协作。我们写的代码部分不用关心线程问题,代码也主要由一堆callback回调构成,然后主线程在循环过程中适时调用这些代码。单线程除了保证Node.js高性能之外,还保证了绝对的线程安全,使开发者不用担心同一变量同时被多个线程读写而造成程序崩溃。

Node.js 的 单线程

事件循环: 通俗的来讲,事件循环就是一个程序启动期间运行的死循环,没有任何特别之处。客户端请求建立连接,提交数据等行为,会触发相应的事件,调用对应的事件处理回调函数。在Node中,一个时刻只能处理一个回调函数,但是在执行一个回调函数的中途,可以转而处理其他事件,然后继续返回执行原事件的回调函数,这种处理机制,称为‘事件环’机制。

Node.js 的 事件循环

非阻塞io:  IO都是阻塞的,而Node.js却说自己是非阻塞IO,那么只能说明一点,IO肯定不是由Node.js来处理, Node.js会把IO这项工作分配给别人来做,别人IO完了,再事件通知Node.js,将IO结果重新加入排队,等待被处理

 

Node与Npm

在Node.js中,以模块为单位划分所有功能,并提供了一个完整的模块加载机制,这使得我们可以将应用程序划分为各个不同的部分,并且对这些部分进行很好的协同管理。通过将各种可重用代码编写在各种模块中的方法,我们可以大大减少应用程序代码量,提高应用程序的开发效率以及应用程序代码的可读性。通过模块加载机制,我们可以将各种第三方模块引入到我们的应用程序中。Node.js 提供了一个npm包管理工具,用于从第三方网站上下载各种Node.js包。

 

Node模块的加载

Node.js使用CommonJS规范加载模块(同步加载模块,只有模块加载完成,才能执行后面的操作)

CommonJS规范将每个文件都看作一个模块,模块内部的变量都是私有的,无法被其他模块使用,除非是用预定义的方法将内部的变量暴露出来(通过exports 和 require关键字来实现)

require引用模块示例:

// we.js 定义了一个简单的自定义模块
var
we = { my: function() { console.log('I am 220...') }, you: function() { console.log('I am 284...') } } module.exports = we

 这样就实现了一个自定义模块,该模块提供了一个接口,然后使用module.exports 将该接口暴露给外部使用.

var we = require('./we.js')
we.my()

 外部代码想要使用we.js中的方法,需要使用require关键字引入该接口。

require的缓存策略:

Node会自动缓存经过require引入的文件,使得下次再引入不需要经过文件系统而是直接从缓存中读取。

var we = require('./we.js')
console.log(require.cache)

// 输出内容如下,我们可以在这里找到很多有用的信息,
// 例如path表示模块引入时Node的查找路径,即从当前目录下的node_modules开始,一直到磁盘根目录为止
{ 'C:\Users\wangr\Desktop\Node\main.js': Module { id: '.', exports: {}, parent: null, filename: 'C:\\Users\\wangr\\Desktop\\Node\\main.js', loaded: false, children: [ [Object] ], paths: [ 'C:\\Users\\wangr\\Desktop\\Node\\node_modules', 'C:\\Users\\wangr\\Desktop\\node_modules', 'C:\\Users\\wangr\\node_modules', 'C:\\Users\\node_modules', 'C:\\node_modules' ] }, 'C:\Users\wangr\Desktop\Node\we.js': Module { id: 'C:\\Users\\wangr\\Desktop\\Node\\we.js', exports: { my: [Function: my], you: [Function: you] }, parent: Module { id: '.', exports: {}, parent: null, filename: 'C:\\Users\\wangr\\Desktop\\Node\\main.js', loaded: false, children: [Array], paths: [Array] }, filename: 'C:\\Users\\wangr\\Desktop\\Node\\we.js', loaded: true, children: [], paths: [ 'C:\\Users\\wangr\\Desktop\\Node\\node_modules', 'C:\\Users\\wangr\\Desktop\\node_modules', 'C:\\Users\\wangr\\node_modules', 'C:\\Users\\node_modules', 'C:\\node_modules' ] } }

 

Node核心模块 - http模块

 http模块主要提供了一系列用于网络传输的API,在http模块中,node定义了一些顶级的类、属性以及方法

创建http服务器通常使用createServer方法创建http服务器

// 代码中使用createServer方法创建了一个简单的HTTP服务器,该方法返回一个http.server的实例,
// createServer方法包含了一个匿名的回调函数,该函数有两个参数req和res, 分别是HTTP的request和response对象,
// 服务器创建完成后,Node进程开始循环监听3000端口,
// 当浏览器访问localhost:3000时,Node返回‘Hello World’
const http = require('http') const server = http.createServer(function(req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}) res.end('Hello World') }) server.listen(3000)

Rquest 请求信息对象:当处理http请求时,最先做的事就是获取请求的URL、method等信息。Node将相关信息都封装在一个对象中(回调函数中的req).

const http = require('http')
const server = http.createServer(function(req, res) {

    // 再次请求localhost:3000 
    // 获取请求的  method
    let method = req.method
    console.log(method) 
    // => GET

    // 获取请求的  URL
    let url = req.url
    console.log(url) 
    // => /

    // 获取请求的 header
    let headers = req.headers
    console.log(headers) 
    // => { host: 'localhost:3000',
    // connection: 'keep-alive',
    // 'cache-control': 'max-age=0',
    // 'upgrade-insecure-requests': '1',
    // 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
    // accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    // 'accept-encoding': 'gzip, deflate, br',
    // 'accept-language': 'zh-CN,zh;q=0.9' }

    // 获取请求的 body
    let body = []
    req.on('data', function(chunk) {
        body.push(chunk)
    }).on('end', function() {
        body = Buffer.concat(body).toString()
        console.log(body)
    })

    res.writeHead(200, {'Content-Type': 'text/plain'})
    res.end('Hello World')
})
server.listen(3000)

Response 请求响应对象

设置响应头: response.setHeader 、 response.writeHead 

    // 使用 response.setHeader 设置响应头信息
    res.setHeader('Content-Type', 'application/json')
    // 使用 response.setHeader方法 只能设置单个属性内容
    // 使用 response.writeHead方法 一次性设置所有的响应头和状态码
    res.writeHead(200, {
        'Content-Length': Buffer.byteLength(body),
        'Content-Type': 'text/plain'
    })

设置响应体: response.write、response.end

    // write方法将要发送的数据 存放到流中 调用end方法将该stream发送到客户端
    res.write('<html>')
    res.write('<body>')
    res.write('<h1>Hello,World</h1>')
    res.write('</body>')
    res.write('</html>')
    // 也可以直接将返回数据直接作为end方法的参数进行返回
    res.end('<html><body><h1>Hello World</h1></body></html>')

 

HTTP客户端服务: HTTP模块除了能在服务端处理客户端请求之外,还可以作为客户端向服务器发起请求,

通过http.get发起get请求,通过post方法上传文件等。这也是Node也能做出桌面软件的基础

const http = require('http')
http.get('http://www.baidu.com', function(res) {
    let statusCode = res.statusCode
    if(statusCode === 200) {
        let result = ''
        res.on('data', function(data) {
            result += data
        })
        res.on('end', function() {
            console.log(result.toString())
        })
        res.on('error', function(e) {
            console.log(e.message)
        })
    }
})

创建代理服务器: 代理服务器相当于在客户端和目标服务器之间建立了一个中转,所有的访问和流量都经过这个服务器进行中转,代理服务器在实际中运用十分广泛。例如,如果本地机器不能直接访问目标服务器,那么就在可以连通两端的机器上搭建一个代理服务器,就能通过间接方式访问目标服务器了

// 当我们请求localhost:8080/google.com 的时候
// 就由我们的代理服务器去请求google.com
http.createServer(function(req, res) { let url = req.url.slice(1) let proxyRequest = http.request(url, function(pRes) { res.writeHead(pRes.statusCode, pRes.headers) pRes.on('data', function(data) { res.write(data) }) pRes.on('end', function() { res.end() }) }) req.on('data', function(data) { proxyRequest.write(data) }) req.on('end', function() { proxyRequest.end() }) }).listen(8080)

 

总结:

Node.js强大体现在事件驱动、异步处理、非阻塞IO等方面。

Node.js 擅长对数据库等IO操作频繁的系统中。

Node.js 不擅长CPU密集型的应用、模板渲染、压缩/解压缩、加/解密等操作都是Node.js的软肋

 

posted @ 2018-09-09 22:03  220和284  阅读(140)  评论(1)    收藏  举报