NodeJS-基础

安装

https://nodejs.org/en/download/

安装nvm

nodejs多版本切换

window,github中搜索nvm-windows下载

nvm list 查看当前所有的node版本

nvm install v10.13.0 安装指定版本

nvm use --delete-prefix 10.13.0 切换到指定版本

nodejs和js的区别

ECMAScript是语法规范

nodejs = ECMAScript + nodejs API

server开发和前端开发的区别

服务稳定性

  server端可能会遭受各种恶意攻击和误操作

  单个客户端可以意外挂掉,但是服务端不能

  使用PM2做进程守候

考虑内存和CPU(优化,扩展)

  客户端独占一个浏览器,内存和CPU都不是问题

  server端要承载很多请求,CPU和内存都是稀缺资源

  使用stream写日志,使用redis存session

日志记录

  前端也会参与写日志,但是日志的发起方,不关心后续

  server端要记录日志,存储日志,分析日志,前端不关心

安全

  server端随时准备接受各种恶意攻击,前端则少很多

  如:越权操作,数据库攻击

  预防xss攻击和sql注入

集群和服务拆分

  产品发展速度快,流量可能会迅速增加

  如何通过扩展机器和服务器拆分来承载大流量

自动重启工具

安装

npm install -g supervisor

启动

supervisor app.js

或者使用nodemom

安装

node install -g nodemom

启动

node app.js

调试

inspect

chrome://inspect/

安装插件NIM

node --inspect-brk a.js

process

参数相关 argv/argv0/execArgv/execPath

const {argv} = require('process')

argv.forEach((val, index) => {
  console.log(`${index}:${val}`)
})
// 0:D:develtools
odejs
ode.exe
// 1:F:ProjectNodeJSlearnlearna.js
// 2:--s
// 3:a
// 4:b
// 5:c
View Code

环境 env

cwd()

nextTick

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

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

setTimeout(() => {
  console.log('setTimeout1')
},100)

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

path

normalize 规范path,解析.. 和 .

path.normalize('/foo/bar//baz/asdf/quux/..');
// 返回: '/foo/bar/baz/asdf'
View Code

join 给定的path连接在一起

path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// 返回: '/foo/bar/baz/asdf'
View Code

resolve 把相对路径转换成绝对路径

resolve('./')
View Code

basename  扩展名

path.basename('/foo/bar/baz/asdf/quux.html');
// 返回: 'quux.html'
View Code

dirname 返回path的目录名

path.dirname('/foo/bar/baz/asdf/quux');
// 返回: '/foo/bar/baz/asdf'
View Code

exname 返回path的扩展名

path.extname('index.html');
// 返回: '.html'
View Code

path 返回path对象

path.parse('/home/user/dir/file.txt');
// 返回:
// { root: '/',
//   dir: '/home/user/dir',
//   base: 'file.txt',
//   ext: '.txt',
//   name: 'file' }
View Code

format 与path相反

// 如果提供了 `dir`、 `root` 和 `base`,
// 则返回 `${dir}${path.sep}${base}`。
// `root` 会被忽略。
path.format({
  root: '/ignored',
  dir: '/home/user/dir',
  base: 'file.txt'
});
// 返回: '/home/user/dir/file.txt'

// 如果未指定 `dir`,则使用 `root`。 
// 如果只提供 `root`,或 'dir` 等于 `root`,则将不包括平台分隔符。 
// `ext` 将被忽略。
path.format({
  root: '/',
  base: 'file.txt',
  ext: 'ignored'
});
// 返回: '/file.txt'

// 如果未指定 `base`,则使用 `name` + `ext`。
path.format({
  root: '/',
  name: 'file',
  ext: '.txt'
});
// 返回: '/file.txt'
View Code

sep

'foo/bar/baz'.split(path.sep);
// 返回: ['foo', 'bar', 'baz']
View Code

delimiter

console.log(process.env.PATH);
// 打印: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin'

process.env.PATH.split(path.delimiter);
// 返回: ['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin']
View Code

__dirname/process.cwd()/path.resolve('./)  

__dirname  返回当前文件的磁盘路径

process.cwd() 返回的是执行node命令所在文件夹

console.log(__dirname)

console.log(process.cwd())

console.log(path.resolve('./'))
View Code

Buffer

处理二进制数据流

实例类似整数数组,大小固定

C++代码在V8堆外分配物理内存

// 创建一个长度为 10、且用零填充的 Buffer。
const buf1 = Buffer.alloc(10);

// 创建一个长度为 10、且用 0x1 填充的 Buffer。 
const buf2 = Buffer.alloc(10, 1);

// 创建一个长度为 10、且未初始化的 Buffer。
// 这个方法比调用 Buffer.alloc() 更快,
// 但返回的 Buffer 实例可能包含旧数据,
// 因此需要使用 fill() 或 write() 重写。
const buf3 = Buffer.allocUnsafe(10);

// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);

// 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
const buf5 = Buffer.from('tést');

// 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from('tést', 'latin1');
View Code

Buffer.byteLength

因为占2个自己,中文占3个自己

const str = 'u00bd + u00bc = u00be';

console.log(`${str}: ${str.length} 个字符, ` +
            `${Buffer.byteLength(str, 'utf8')} 个字节`);
// 打印: ½ + ¼ = ¾: 9 个字符, 12 个字节
View Code

Buffer.concat

// 用含有三个 `Buffer` 的数组创建一个单一的 `Buffer`。
const buf1 = Buffer.alloc(10);
const buf2 = Buffer.alloc(14);
const buf3 = Buffer.alloc(18);
const totalLength = buf1.length + buf2.length + buf3.length;

console.log(totalLength);
// 打印: 42

const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);

console.log(bufA);
// 打印: <Buffer 00 00 00 00 ...>
console.log(bufA.length);
// 打印: 42
View Code

Buffer.isBuffer

Buffer.from

buf.fill

buf.equals

buf.indexOf

http模块

const http = require('http')

http.createServer((req, res) => {
  res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'})
  res.end('Hello World!')
}).listen(3000)
View Code

我们可以看出NodeJS不及是一个应用还是一个HTTP服务器

url模块

url.parse()

url.parse('http://localhost:3000')
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'localhost:3000',
  port: '3000',
  hostname: 'localhost',
  hash: null,
  search: null,
  query: null,
  pathname: '/',
  path: '/',
  href: 'http://localhost:3000/' }
> url.parse('http://localhost:3000?name=Susan&age=18')
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'localhost:3000',
  port: '3000',
  hostname: 'localhost',
  hash: null,
  search: '?name=Susan&age=18',
  query: 'name=Susan&age=18',
  pathname: '/',
  path: '/?name=Susan&age=18',
  href: 'http://localhost:3000/?name=Susan&age=18' }
> url.parse('http://localhost:3000?name=Susan&age=18', true)
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'localhost:3000',
  port: '3000',
  hostname: 'localhost',
  hash: null,
  search: '?name=Susan&age=18',
  query: [Object: null prototype] { name: 'Susan', age: '18' },
  pathname: '/',
  path: '/?name=Susan&age=18',
  href: 'http://localhost:3000/?name=Susan&age=18' }
View Code

代码

const query = url.parse(req.url, true).query  // 设置为true,get传值转换为对象,如果不设置true,那么是字符串

url.resolve()

> url.resolve('http://localhost:3000', 'index')
'http://localhost:3000/index'
> url.resolve('http://localhost:3000/home', 'index')
View Code

fs模块

stat 获取文件信息,判断是文件或者目录

fs.stat('b', (err, stats) => {
  if (err) return 
  console.log(stats.isFile())
  console.log(stats.isDirectory())
})
View Code

mkdir 创建目录

fs.mkdir('c', err => {
  if (err) return
  console.log('成功创建目录')
})
View Code

writeFile 创建文件并且写入

let data = 'Hello World ,Hi 苏珊'
fs.writeFile('c.md', data, err => {
  if (err) return
  console.log('成功写入文件')
})
View Code

appendFile 追加文件

fs.appendFile('c.md', 'Welcome', err => {
  if (err) return 
  console.log('成功追加文件')
})
View Code

readFile 读取文件

fs.readFile('c.md', 'utf-8', (err, data) => {
  if (err) return
  console.log(data.toString())
})
View Code

readdir 读取文件目录

fs.readdir('static', (err, files) => {
  if (err) return 
  console.log(files)
})
View Code

rename 重命名

fs.rename('c.md', 'a.md', err => {
  if (err) return 
  console.log('成功重命名')
})
View Code

rmdir 删除目录

fs.rmdir('c', err => {
  if (err) return 
  console.log('成功删除目录')
})
View Code

unlink 删除文件

fs.unlink('b', err => {
  if (err) return 
  console.log('成功删除文件')
})
View Code

createReadStream 从文件流中读取数据

let readStream = fs.createReadStream('data.json')
let str = '' 
readStream.on('data', chunk => {
  str += chunk
})

readStream.on('end', () => {
  console.log(str)
})

readStream.on('error', err => {
  console.log(err)
})
View Code

createWriteStream 写入文件

let data = 'Hi,苏珊'
let writeStream = fs.createWriteStream('a.md')

writeStream.write(data, 'utf-8')

writeStream.end()

writeStream.on('finish', () => {
  console.log('写入完毕')
})

writeStream.on('error', err => {
  console.log(err)
})
console.log('执行完毕')
View Code

util的promisify解决回调地域

const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);
stat('.').then((stats) => {
  // Do something with `stats`
}).catch((error) => {
  // Handle the error.
});
View Code
const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);

async function callStat() {
  const stats = await stat('.');
  console.log(`This directory is owned by ${stats.uid}`);
}
View Code

events

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('触发事件');
});
myEmitter.emit('event');
View Code

this指向

const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
  console.log(a, b, this, this === myEmitter);
  // 打印:
  //   a b MyEmitter {
  //     domain: null,
  //     _events: { event: [Function] },
  //     _eventsCount: 1,
  //     _maxListeners: undefined } true
});
myEmitter.emit('event', 'a', 'b');
View Code
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  console.log(a, b, this);
  // 打印: a b {}
});
myEmitter.emit('event', 'a', 'b');
View Code

只执行一次

const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// 打印: 1
myEmitter.emit('event');
// 不触发
View Code
原文地址:https://www.cnblogs.com/sonwrain/p/10624967.html