zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    HashMap遍历和使用
    java的环境变量classpath中加点号 ‘.’ 的作用
    java编程思想-第六章-某些练习题
    内连接查询 (select * from a join b on a.id = b.id) 与 关联查询 (select * from a , b where a.id = b.id)的区别
    django入门-模型-part2
    django入门-初窥门径-part1
    jdk8飞行记录器配置
    docker-compose启动的tomcat无法远程连接jmx
    zabbix_sender自定义监控
    搭建基于Jenkins salt-api的运维工具
  • 原文地址:https://www.cnblogs.com/sonwrain/p/10624967.html
Copyright © 2011-2022 走看看