Nodejs入门(1)

By admin in 4858美高梅 on 2019年4月6日

一、Nodejs介绍

1、nodejs是ecmascript的runtime

2、nodejs使用了event-driven(事件驱动)non-blocking I/Omodel(无阻塞的io模型)

  • 非阻塞:I/O时函数立刻回到,进度不等I/O实现
  • event-driven:Nodejs靠事件开始展览驱动

3、cpu密集 vs I/O密集

  • cpu密集:压缩、解压、加密、解密
  • I/O密集:文件操作、网络操作、数据库

因为JS操作是I/O密集,所以Nodejs是JS在serves上面的runtime

四、高并发应对之道

  • 日增机器数
  • 充实每台机械的cpu数

5、Nodejs单线程

  • 单线程只针对主进度,I/O操作系统底层102线程调度(Nodejs本身是单线程,但它有壹部分义务交给操作系统本身去做102线程)
  • 单线程不是单进度

陆、Nodejs应用场景

  • Web Server
  • 地面代码构建(编译之类)

nodejs 是什么

nodejs is a JavaScript runtime built on Chrome’s V8
nodejs 并不是1门语言,而是二个周转条件
特点:

  • 事件驱动
  • 非阻塞 I/O

4858美高梅 1

什么是NodeJS

Node.js选用模块化结构,依照CommonJS规范定义和使用模块。模块与公事是各类对应提到,即加载2个模块,实际上正是加载对应的二个模块文件。
 JS是脚本语言,脚本语言都急需1个解析器才能运作。对于写在HTML页面里的JS,浏览器充当精通析器的剧中人物。而对于要求单独运作的JS,NodeJS就是三个解析器。
  每1种解析器都以三个周转条件,不但允许JS定义各类数据结构,举行各样计算,还同意JS使用运转条件提供的放置对象和章程做1些业务。例如运营在浏览器中的JS的用途是操作DOM,浏览器就提供了document之类的松开对象。而运营在NodeJS中的JS的用途是操作磁盘文件或搭建HTTP服务器,NodeJS就相应提供了fs、http等内置对象。
  Node.js
被规划用来支付大规模高并发的网络采取,这种互连网选用的瓶颈之一是在 I/O
的拍卖功能上。由于硬件及互联网的限量,I/O
的快慢往往是稳定的,如何在在此以前提下尽可能处理越来越多的客户请求,提升 CPU
使用效用,便成了开发人士面临的最大标题。得益于基于事件驱动的编制程序模型,Node.js
使用单壹的 伊芙nt loop 线程处理客户请求,将 I/O
操作分派至各异步处理模块(那里一般人不清楚,node.js包罗众多模块,那一个模块能够应用js直接调用系统的api),既缓解了单线程方式下
I/O 阻塞的题材,又制止了八线程形式下能源分配及侵夺的标题。

2、Nodejs开发环境与调节工具

1、环境

  • CommonJS 规范
  • global 对象(类似于js里面的window对象)
  • process 当前举行的长河

2、CommonJS规范

  • 各类文件都以贰个模块,都有和好的作用域
  • 在模块内部module变量代表模块本人
  • module.exports属性代表模块对外接口(将模块的片段事物输出)
  • require规则
    • / 表示相对路径,. / 表示相对于当下文件的
    • 支撑js、json、node的拓展名
  • require特性
    • module被加载的时候会实行3回,并开始展览缓存,第二回直接用缓存里面包车型大巴结果
    • 当一个模块被循环加载(a信赖b,然后b又依赖a),那么只会输出已经实施的局地(a执行在b正视a此前a该执行的片段)

叁、global全局对象

  • CommonJS
  • Buffer、process、console
  • timer

非阻塞I/O

  • 卡住:I/O时进程休眠等待I/O实现后展开下一步。
  • 非阻塞:I/O时函数马上重临,过程不等待I/O达成。

nodejs.png

单线程方式

客户端发起1个 I/O 请求(数据库查询),然后等待服务器端再次回到 I/O
结果,结果回到后再对其举办操作,但这种请求日常须求不短日子(对于服务器的
CPU 处理能力来说)。那1经过中,服务器无法经受新的乞请,即阻塞式
I/O。那种处理格局尽管简易,却不实用,特别是面对大气呼吁的时候,简直就不可用。那种景观类似在轻轨站领票窗口排队领票,假设你在新岁佳节之间去法国首都轻轨站排队买过票,绝不会认为那是1种好的处理格局。庆幸的是,未来很少有服务器采用这种处理格局。

事件驱动

  • I/O等异步操作甘休后的通报
  • 旁观者形式

嵌入概念

二十多线程格局

该办法下,服务器为各类请求分配3个线程,全体职务均在祥和的线程内实施,就像是火车站多开了多少个卖票窗口,处理成效高了无数。但就好像读者看到的那么,在年节期间各样购票窗口前照旧人山人海,为啥轻轨站不再多开部分领票窗口呢?当然是因为资金。线程也壹致,服务器每成立二个线程,各种线程大约会占有
2M
的系列内部存款和储蓄器,而且线程之间的切换也会骤降服务器的拍卖功用,基于花费的思量,那种处理格局也有肯定的局限性。然则,那却不是最首要的,首要的是付出多线程程序格外辛劳,容易失误。程序员需考虑死锁,数据不壹样等难题,四线程的顺序极难调节和测试和测试。基本上在程序运营出错的时候,程序员才晓得自身的主次有荒唐。而那种漏洞非常多的代价往往又是巨大的,那些访问量巨大的电子商务网站日常会曝出价格错误等造成商行损失的新闻。

为什么前端偏爱nodejs

  • 前端任务范围变大,统1/10本体验
  • 在处理高并发,I/O密集场景品质优势远近著名

Nodejs入门(1)。CPU密集

拓展的1对收缩,解压,加密,解密等计算都属于CPU密集

事件驱动

客户发起 I/O 请求的还要传入一个函数,该函数会在 I/O
结果重临后被机关调用,而且该请求不会阻塞后续操作。就好像电话购票,设想你一大早赶到办公,给火车站打个电话,将本人的票务消息,地址告诉对方,然后放下电话,泡杯茶,浏览一下网页,回复一下明天的电子邮件,你完全不用管火车票的事了,假若订到票,高铁站会派快递公司按您电话中关系的联系格局送票给你。无疑,那是一种极其美丽的处理形式。全体请求以及同时传入的回调函数均发送至同壹线程,该线程平常称为
伊芙nt loop 线程,该线程负责在 I/O
执行达成后,将结果回到给回调函数。那里要留心的是 I/O
操作自身并不在该线程内执行,所以不会阻塞后续请求。比如:请求a要访问数据库,请求b要访问文件系统,倘使伊夫nt
loop先接受到a请求,这时伊芙nt
loop会把a的回调方法交给处理访问数据库的异步处理模块。然后伊芙nt
loop就足以去领受请求b,并把b的回调方法交给处理文件系统的1部处理模块。然后伊夫nt
loop继续守候请求。当访问数据的异步处理模块处理完了后,会再接再砺调用a的回调方法。在a的回调方法中,就会给客户a发送查询到的多少(当然那里要求短短的运用伊夫nt
loop来操作)。

CPU密集 VS I/O密集

  • CPU密集: 压缩、解压、加密、解密
  • I/O密集: 文件操作、互联网操作、数据库

I/O密集

文本的读取,互联网操作,数据库等操作时,为I/O密集

干什么选取 JavaScript

实则,在落到实处 Node.js 之初,小编 Ryan Dahl 并不曾选取JavaScript,他尝试过
C、Lua,皆因其欠缺一些高等语言的特征,如闭包、函数式编制程序,致使程序繁复,难以维护。而
JavaScript 则是永葆函数式编制程序范型的语言,很好地切合了 Node.js
基于事件驱动的编制程序模型。加之 谷歌 提供的 V八 引擎,使 JavaScript
语言的施行进程大大提升。最后突显在我们前边的就成了 Node.js,而不是
Node.c,Node.lua
或其余语言的落实。Javascript的匿名函数和闭包天性非凡适合事件驱动、异步编制程序。Javascript在动态语言中质量较好,有开发人士对Javacript、Python、Ruby等动态语言做了质量分析,发现Javascript的性子要好于别的语言,再添加V8引擎也是同类的佼佼者,所以Node.js的质量也沾光个中。
  Node.js采纳C++语言编写而成,是八个Javascript的运转条件。为何采用C++语言呢?据Node.js开创者RyanDahl纪念,他早期梦想利用Ruby来写Node.js,可是后来意识Ruby虚拟机的性质不可能满意她的要求,后来她尝试接纳V捌引擎,所以选拔了C++语言。
  Node.js选取了谷歌Chrome浏览器的V捌引擎,品质很好,同时还提供了诸多系统级的API,如文件操作、互连网编制程序等。
  Node.js是2个后端的Javascript运维环境(帮忙的系统包罗Linux、Windows),那意味着你能够编写系统级恐怕服务器端的Javascript代码,交给Node.js来诠释实施。

web 常见现象

  • 静态能源读取
  • 数据库操作
  • 渲染页面

高并发

单位时间内的访问量

多核处理器意况下

NodeJS中的JavaScript确实是在单线程上执行,不过作为宿主的NodeJS,它自己并非是单线程的,NodeJS在I/O方面又选取到一小部分附加的线程协理实现异步。程序员未有机会直接开立线程,那也是一对同学想当然的以为NodeJS的单线程不能够很好的选取多核CPU的因由,他们竟然会说,莫明其妙由三人1齐合营开发二个单线程的次第。
  NodeJS封装了里面包车型地铁异步实现后,导致程序员不能直接操作线程,也就造成全部的业务逻辑运算都会丢到JavaScript的履行线程上,那也就象征,在高并发请求的时候,I/O的难点是很好的缓解了,然则富有的事体逻辑运算积少成多地都运作在JavaScript线程上,形成了一条拥挤的JavaScript运算线程。NodeJS的缺陷在那年会暴流露来,单线程执行运算形成的瓶颈,拖慢了I/O的频率。那大约能够算得上是凝聚运算处境下不能很好利用多核CPU的通病。那条拥挤的JavaScript线程,给I/O形成了质量上限。
  不过,事情又不要相对的。回到前端浏览器中,为了解决线程拥挤的事态,Web
Worker应运而生。而同样,Node也提供了child_process.fork来创制Node的子进度。在3个Node进度就能很好的缓解密集I/O的气象下,fork出来的别的Node子进度能够看作常驻服务来消除运算阻塞的标题(将运算分发到多少个Node子进度中上去,与Apache创立多少个子进度类似)。当然child_process/Web
Worker的建制永远只可以化解单台机器的题材,大的Web应用是不容许1台服务器就能形成有着的伸手服务的。拜NodeJS在I/O上的优势,跨OS的多Node之间通讯的是不算什么难点的。消除NodeJS的演算密集难题的答案其实也是非常简单的,便是将运算分发到多个CPU上。

高并发应对之道

  • 扩充机器数
  • 充实每台机器的CPU数——多核

进程

是电脑中的程序关于某数码集合上的三次运转活动,是系统进行能源分配和调度的大旨单位

模块

编排稍大学一年级些的次第时一般都会将代码模块化。在NodeJS中,1般将代码合理拆分到分化的JS文件中,每叁个文书正是1个模块,而文件路径就是模块名。
  在编制各样模块时,都有require、exports、module几个优先定义好的变量可供使用。

进程

  • 进度:是电脑中的程序关于某数码集合上的叁遍运营活动,是系统进行财富分配和调度的主题单位
  • 多进程:运营几个进程,五个经过能够一块执行多少个任务

NodeJS工作模型

4858美高梅 2

image.png

那时候,NodeJS能够拍卖很多用户发来的片段伸手,而那写请求不会因为调用I/O操作而空闲,相当于非阻塞I/O,CPU能够不停的进展收纳请求,并拓展I/O操作,而I/O操作则是二10多线程的,当I/O操作完结后,CPU再讲数量再次回到给客户端.NodeJS消除了CPU上的悠闲和处理高并发的能力

require

require函数用于在现阶段模块中加载和采用其他模块,传入3个模块名,再次回到二个模块导出对象。模块名可使用相对路径(以./初叶),大概是相对路径(以/或C:之类的盘符开端)。

nodejs 环境

  • nodejs
    官网:https://nodejs.org/en/
  • CommonJS: 模块化规范
  • global: 全局对象,nodejs 未有 DOM、BOM,全局是global
  • process: 进程

线程

进度内四个对峙独立的,可调度的推行单元,与同属1个进程的线程共享进程的财富

exports

exports对象是时下模块的导出对象,用于导出模块公有方法和质量。其余模块通过require函数使用当前模块时获得的正是近年来模块的exports对象。

2个板栗

4858美高梅 3

image

nodejs 自动帮大家做了,外面包了三个函数,落成模块化。

多线程

运维一个历程,在1个历程内开发银行八个线程,那样,四个线程也能够1块执行多少个职分

module

经过module对象足以访问到近来模块的有的连锁新闻,但最多的用途是替换当前模块的导出对象。例如模块导出对象暗中同意是一个日常对象,如若想改成四个函数的话,能够行使以下办法。

module.exports = function () {
    console.log('Hello World!');
};

以上代码中,模块默许导出对象被替换为3个函数。

CommonJS

  • 种种文件是一个模块,有谈得来的成效域,比如上边栗子,外面包裹了一个函数,就改为了1部分功能域了。
  • 在模块内部 module 变量代表模块本身。
  • module.exports 属性代表模块对外的接口

NodeJS单线程

单线程只是针对主进度,I/O操作系统底层拾二线程调度. 单线程并不是单进程

模块开端化

3个模块中的JS代码仅在模块首次被接纳时实施二次,并在执行进程中发轫化模块的导出对象。之后,缓存起来的导出对象被另行利用。

require 规则

  • / 表示相对路径,./ 表示相对于近年来文件的相对路径
  • 支持 js、json、node 拓展名,不写的话就会挨个尝试。
  • 不写路径则认为是 build-in 内部自带的模块也许各级 node_modules
    内的第叁方模块。

环境

主模块

因而命令行参数字传送递给NodeJS以运行程序的模块被誉为主模块。主模块负责调度组成总体程序的任何模块形成工作。例如通过以下命令运行程序时,main.js正是主模块。

node main.js

require 特性

  • module
    被加载的时候实施,加载后缓存,也就率先次加载并进行,第叁次有缓存就不加载了。
  • 假若出现某些模块被循环加载,就只输出已施行的一部分,还未执行的1部分不会输出。(太绕了,要防止循环引用)

CommonJS

每一种文件是三个模块,有投机的成效域
在模块内部module变量代表模块本身
module.exports属性代表模块对外接口

二进制模块

就算如此1般大家应用JS编写模块,但NodeJS也支持使用C/C++编写2进制模块。编写翻译好的贰进制模块除了文件扩充名是.node外,和JS模块的行使办法1样。尽管二进制模块能利用操作系统提供的兼具成效,拥有极其的潜能,但对于前端同学而言编写过于劳累,并且难以跨平台选拔。

nodejs 内置模块

api文档

  • fs 文件系统模块,用来做文件的读写,
require 规则
  • / 表示绝对路径,./代表相对于当下文件的门径
  • 扶助js,json,node扩张名,不写二次尝试
  • 不写路径则认为是build-in模块也许各级node_modules内的第二方模块

其三方模块 node_modules

  • chalk 模块,能够让输出带颜色。

    4858美高梅 4

    image

![](https://upload-images.jianshu.io/upload_images/5051517-c16d8c1917129f29.jpg)

image
require 特性
  • module被加载的时候实施,加载后缓存
  • 倘使出现有个别模块被循环加载,就只输出已经执行的局地,还未实行的片段不会输出

module.exports 与 exports 的区别

const exports = modules.exports
    //exports 是 module.exports 的快捷方式

exports.test = 100;
    //可以给 exports 添加属性。

exports = {
    test: 150
}   //这是错误的用法,因为改变了 exports 的指向,模块输出找不到。

module.exports = {
    test: 200
}   //这是可以的,因为输出的模块是 module.exports
module.exports与exports的区别
const exports = module.exports // exports就是module.exports的简写

(
    function(exports, require, module, __filename, __dirname) {
        // code
    }
)
exports.test = 100

exports = {
    a: 1,
    b: 2
}

若是写成exports,那么exports的指向就会被更改,它不再指向module.exports,也就如何都未有出口
因此:

module.exports = {
    a: 1,
    b: 2
}

那会儿,module.exports将本着了这一个目的,即出口了那么些目的

模块对外的出口永远是module.exports,你能够加上它的属性,不过你不能够改改它的对准,倘若exports的对准被涂改,那么它将不会对外输出

global 全局对象

  • CommonJS
  • Buffer:处理2进制数据流
  • process:进程
  • console
  • timer

把变量赋给 global 对象作为品质,则具有的文书都能得到该变量。

global

  • CommonJS
  • Buffer,process,console
  • timer

// mod1
global.test = 100
// mod2
console.log(test)  // 100

timer

  • setImmediate:下二个事件队列的队首。
  • setTimeout:定时执行,最快是在多个事件队列之间。
  • process.nextTick:当前事件队列的队尾。

来看一下八个的实施顺序

4858美高梅 5

image

4858美高梅 6

image

能够观察,执行顺序是 nextTick
setImmediate要早,而setTimeout由设定的时间来支配,要是时光为0,则是在四个事件队列之间。

process

const {argv, argv0, execArgv, execPath} = process
// argv 启动这个process的时候的所有参数
// argv0 保存了argv这个数组的引用
// execArgv 调用node所调用的特殊参数
// execPath argv的第一个参数
argv.forEach(item => {
    console.log(item)
})

const {env} = process
console.log(env)   // 执行环境

console.log(process.cwd())  // 当前命令所执行的路径

setImmediate(() => {
    console.log('setImmediate')
})

setTimeout(() => {
    console.log('setTimeout')
}, 0);

process.nextTick(() => {
    console.log('nextTick')
})

nextTick是将其坐落了最近队列的队尾,而setImmediate是坐落了下3个连串的队尾,set提姆eout是坐落两者之间

基础API

normalaize

拍卖途径

const {normalize} = require('path')
console.log(normalize('/usr//local/bin'))

join

东拼西凑路径

const {join} = require('path')
console.log(join('/usr', 'local', 'bin/'))

resolve

相对路径解析为相对路径

const {resolve} = require('path')
console.log(resolve('./'))

basename dirname extname

const {basename, dirname, extname} = require('path')
const filePath = '/usr/local/bin/no.txt'
console.log(basename(filePath)) // 文件名
console.log(dirname(filePath)) // 路径
console.log(extname(filePath)) // 扩展名

parse format

解析路径

const {parse, format} = require('path')
const filePath = '/usr/local/include'
const ret = parse(filePath)
console.log(ret)
console.log(format(ret))    // 将拆分的路径执行回来

输出

{ root: '/',
  dir: '/usr/local',
  base: 'include',
  ext: '',
  name: 'include' }

sep delimiter win32 posix

和操作系统相关的片段事物

const {sep, delimiter, win32, posix} = require('path')
console.log('sep:', sep)    // 路径分隔符 /
console.log('win sep', win32.sep) // \
console.log('PATH:', process.env.PATH)  
// PATH: /Library/Frameworks/Python.framework/Versions/3.6/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin 
console.log('delimiter:', delimiter) // :
console.log('win delimiter:', delimiter) // :
总结

__dirname,__filename 总是回到文件的相对路径
process.cwd()总是回到执行node命令所在文件夹

Buffer

处理二进制数据流 实例类似整数数组,大小固定

console.log(Buffer.alloc(10))
console.log(Buffer.alloc(5, 1))
console.log(Buffer.allocUnsafe(5,1))
console.log(Buffer.from([1,2,3]))
console.log(Buffer.from('test'))

<Buffer 00 00 00 00 00 00 00 00 00 00>
<Buffer 01 01 01 01 01>
<Buffer 18 e3 04 04 01>
<Buffer 01 02 03>
<Buffer 74 65 73 74>

console.log(Buffer.byteLength('test'))  // 字节长度
console.log(Buffer.byteLength('测试'))    
console.log(Buffer.isBuffer({}))     // false
console.log(Buffer.isBuffer(Buffer.from([1, 2, 3])))     // true

const buf1 = Buffer.from('h')
const buf2 = Buffer.from('e')
const buf3 = Buffer.from('l')
const buf4 = Buffer.from('l')
const buf5 = Buffer.from('o')

const buf = Buffer.concat([buf1, buf2, buf3, buf4, buf5])
console.log(buf)    // 连接buffer

const buf = Buffer.from('this is a test')
/* buf.length
buf.toString()
buf.fill()    // 填充
buf.equals()    
buf.indexOf()
buf.copy() */

events

const EventEmitter = require('events')

class CustomEvent extends EventEmitter {

}
const ce = new CustomEvent()
ce.on('test', () => {
    console.log('this is a test')
})
setInterval(() => {
    ce.emit('test')
}, 500)

const EventEmitter = require('events')

class CustomEvent extends EventEmitter{}

const ce = new CustomEvent()

ce.on('error', err => {
    console.log(err)
})

ce.emit('error', new Error('oops'))

施行三遍

import { setInterval } from 'timers';

const EventEmitter = require('events')

class CustomEvent extends EventEmitter{}

const ce = new CustomEvent()

ce.once('test', () => {
    console.log('test event')
})

setInterval(() => {
    ce.emit('test')
}, 500)

移除

const EventEmitter = require('events')
class CustomEvent extends EventEmitter{}
const ce = new CustomEvent()
function fn1() {
    console.log('fn1')
}

ce.on('test', fn1)
ce.on('test', fn2)

setInterval(() => {
    ce.emit('test')
}, 500)

setTimeout(() => {
    ce.removeListener('test', fn2)
}, 1500);

4858美高梅,fs

读文件

const fs = require('fs')

fs.readFile('./module2.js','utf8', (err, data) => {
    if (err) throw err
    console.log(data)
})

同步操作

const data = fs.readFileSync('./module1.js', 'utf8')
console.log(data)

写文件

const fs = require('fs')

fs.writeFile('./text', 'this is a test', {
    encoding: 'utf8'
}, err => {
    if(err) throw err
    console.log('done')
})

查阅文件状态

const fs = require('fs')

fs.stat('./fs.js', (err, stats) => {
    if(err) throw err
    console.log(stats.isFile())
    console.log(stats.isDirectory())
    console.log(stats)
})

重命名

const fs = require('fs')

fs.rename('./text', 'text.txt', err => {
    if (err) throw err
})

打字与印刷目录的文本名

const fs = require('fs')

fs.readdir('../', (err, files) => {
    if (err) throw err
    console.log(files)
})

删去文件夹

const fs = require('fs')

fs.rmdir('./text', err => {
    if(err) throw err
})

蹲点文件或目录的转移

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有