资讯详情

node express mysql koa学习笔记

Enode.js 是基于v8 JavaScript引擎的 JavaScript运行时环境

任何可用的 JavaScript所有实现的应用最终都会实现 使用 JavaScript 实现

1.全局对象和模块化开发

1.1 给node 程序传递参数

当我们 执行 node ./index.js 其实后面可以拼接参数,参数就是 node 的全局对象 process ,比如 node ./index.js ddg age=20

  argv: [     'E:\\node\\node.exe',     'F:\\web前端开发\\自学\\coderwhy-node\\code\\01_learn-node\\02_给node传递参数\\index.js',     'ddg',     'age=20'   ], 
// console.log(process); // process 是 node 的 全局对象 // process 第一层节点,有一个 argv 节点, 它表示参数 // argv : argument vector 缩写,表示 具体参数进入 console.log(process.argv);  process.argv.forEach(item => { 
             console.log(item); }) 

1.2 node 的输出方式

  • console.log() 输入内容最常用的方式 console.log
  • 清空控制台 console.clear
  • console.trace() 查看函数的 调用栈
// console.log(process); // process 是 node 的 全局对象 // process 第一层节点,有一个 argv 节点, 它表示参数 // argv : argument vector 缩写,表示 具体参数进入 console.log(process.argv);  console.log(process.argv[2]); console.log(process.argv[3]);  console.clear() // 清空 控制台  process.argv.forEach(item => { 
             console.log(item); })  function foo() { 
             ar()
}
function bar() { 
        
    console.trace()
    // trace 是可以打印 函数 的 调用栈的 

    // 输出结构如下
    // at bar 表示 这个输出 在 bar 函数 里面执行
    // at foo 表示 bar 函数 是在 foo 函数里面被调用
    // at Object 表示 foo 在全局调用, node 会把他当成 匿名函数调用
    /* Trace at bar (F:\web前端开发\自学\coderwhy-node\code\01_learn-node\02_给node传递参数\02_Node程序的输出.js:20:13) at foo (F:\web前端开发\自学\coderwhy-node\code\01_learn-node\02_给node传递参数\02_Node程序的输出.js:17:5) at Object.<anonymous> (F:\web前端开发\自学\coderwhy-node\code\01_learn-node\02_给node传递参数\02_Node程序的输出.js:36:1) at Module._compile (internal/modules/cjs/loader.js:1133:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10) at Module.load (internal/modules/cjs/loader.js:977:32) at Function.Module._load (internal/modules/cjs/loader.js:877:14) at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) at internal/main/run_main_module.js:18:47 */
}
foo()

node的输出方式官方文档

1.3 node 全局对象

1.3.1 特殊的全局对象

这些全局对象实际上是模块中的变量,只是每个模块都有,看起来像是全局变量,在命令行交互中是不可以使用的

包括 __dirname、__filename、exports、module、require()

  • dirname: 获取当前文件所在的路径,不包括后面的文件名
  • filename 获取当前文件所在的路径和文件名称,包括文件名称
console.log(__dirname);
// F:\web前端开发\自学\coderwhy-node\code\01_learn-node\03_node中的全局变量
console.log(__filename);
// F:\web前端开发\自学\coderwhy-node\code\01_learn-node\03_node中的全局变量\01_特殊的全局对象.js
1.3.2 常见全局对象
  • process 提供了 node 进程中相关的信息
  • 后面在项目中,我也会讲解,如何将一些环境变量读取到 process 的 env 中
  • node 的运行环境、参数信息等等

可以看官方文档


  • setTimeout(callback,delay[,…args]):callback,在 delay毫秒后执行一次
  • setIneterval(callback,delay[,…args]):callback 每 delay 毫秒重复执行一次
  • setImmediate(callback[,…args]):callback I/O 事件后的回调的 “立即” 执行
  • process.nextTick(callback[,…args]):添加到下一次 tick 队列中

global 全局对象
console.log(global);
console.log(global.process);
// 定义变量
var name = "呆呆狗"
console.log(name);
console.log(global.name);// undefined
// node 的顶级对象 是 global ,浏览器的顶级对象是 window,我们在浏览器运行的js文件中var定义的全局变量,是会被挂载到 window 上的,而 global 不会
// global 默认会挂载 process
// 再 node 中,其实每一个文件都是一个模块

2、js 的模块化

2.1 common.js 和 node

commonJS 是一个 规范,最初提出来是再浏览器以外的地方使用,并且当时被命名为 Server.js,后来为了体现他的广泛性,修改为 CommonJS , 平时我们也会简称为 CJS

  • node 是 commonJS 在服务器端 一个具有代表性的实现
  • Browserify 是 CommonJS 在浏览器中的一种实现
  • webpack 打包工具具备对 CommonJS 的支持和转换


// bar.js
const name = "coderwhy"
const age =20

function sayHello(name){ 
        
  console.log('hello' + name);
}

exports.name = name
exports.age = age
exports.sayHello = sayHello
// main.js
const bar = require('./bar')
// 就相当于 bar = exports
// bar 也可以 换成 { name . age .sayHello } 解构赋值
console.log(bar);//{ name: 'coderwhy', age: 20, sayHello: [Function: sayHello] }

console.log(bar.name);
console.log(bar.age);

bar.sayHello('ddg')

2.2 module.exports

  • commonJS 中是没有 module.exports 的概念的
  • 为了实现模块的导出,node 中使用的是 module 的类,每一个模块都是 module 的一个实例 也就是 module
  • 在node 中真正用于导出的其实根本不是 exports 而是 module.exports
  • 因为 module 才是真正的实现者

2.3 require

查找规则

  1. require(传入的是核心模块 fs path 等等) ,则会直接返回,并且停止查找
  2. require(./或者…/ 或者 、/ 根目录) 开头的。没有后缀名则会 直接查找 这个文件 ;查找 文件.js文件 ; 查找 文件.json 文件;查找 文件.node 文件。 如果直接传一个目录,则会先找这个目录下的 index.js 文件 ; index.json 文件 ; index.node 文件。 如果 这两者都没找到 则报错
  3. 直接是一个字符串 比如 require(‘abc’) ,abc 不是核心模块,则会从当前目录下的 node_modules 文件夹下查找,没有找到 再去上一级目录下的 node_modules 下查找,直到 根目录下的 node_modules 根目录在没找到则会报错
    paths: [
      'F:\\web前端开发\\自学\\coderwhy-node\\code\\01_learn-node\\04_js-module\\02_commonjs\\node_modules',
      'F:\\web前端开发\\自学\\coderwhy-node\\code\\01_learn-node\\node_modules',
      'F:\\web前端开发\\自学\\coderwhy-node\\code\\node_modules',
      'F:\\web前端开发\\自学\\coderwhy-node\\node_modules',
      'F:\\web前端开发\\自学\\node_modules',
      'F:\\web前端开发\\node_modules',
      'F:\\node_modules'
    ]

// console.log(module)

2.4 模块加载的过程

  • 模块在被第一次引入的时候,模块中的js代码会被运行一次。是同步执行的
  • 模块被多次引入时,会缓存,最终只会被加载(运行)一次,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKm8W7UQ-1625664086040)(F:\web前端开发\自学\coderwhy-node\coderwhy-node.assets\image-20210629185221783.png)]

此图中,就是循环引入, 就是 图 数据结构, 图结构在遍历的时候,node 采用了 深度优先搜索,所以 main => aaa => ccc => ddd => eee

走到 eee 里面没有引入了,会返回上一层,看看上一层还有没有引入其他的,没有在返回,直到 main,看到还引入了 bbb 则 引入 bbb => ccc

2.5 AMD 规范

AMD 主要是应用于浏览器的一种模块化规范

它采用的是 异步加载模块

事实上 AMD 的规范 还要早于 CommonJS,但是 CommonJS目前依然在被使用,而 AMD 使用的较少了

用起来 是 有点复杂了。需要引入一个 require.js

2.6 CMD 规范

也是一个异步加载模块

但是他将 commonJS 的 优点吸收过来了

seajs 需要用这个依赖文件

2.7 es module

他是 js 的一个模块化系统

  • 它采用了 import 和 export 关键字
  • 采用编译期的静态分析,并且也加入了动态引用的方式
  • export 负责将模块的内容导出
  • import 负责从其他模块导入内容

导出的方式

  • export const age = 20
  • export { } 这只是一个大括号,不是一个对象,这个大括号放置要导出的引用列表
  • export { name as myName } 可以给 name 起一个别名

导入的方式

  • import { name } from ‘路径’ 按需导入
  • import { name as heName } from ‘路径’ 也可以起别名
  • import * as foo from ‘路径’ 把导出的东西,都放到 foo 对象里面

在开发和封装功能的时候,通常希望将暴露 的所有接口放到一个文件中

export { 
          } from './bar.js'
// 这样表示的是,先导入,然后 再导出

默认导出

export default function (){}

import format from ‘./’

我们可以直接给这个默认导出的函数起一个名字


如果 把 import 加载一个模块,放到 逻辑代码中,是不可以的

因为 es module 在被 JS 引擎解析时,就必须要知道他的依赖关系,由于这个时候,无法执行,所以不能确定依赖关系,所有会报错

let flag = true
if (flag) { 
        
  import('./bar.js').then(aaa => { 
        
    console.log()
  })
}

3、常见内置模块

3.1 path

const path = require('path')

// 1、获取路径的信息
const filepath = '/User/ddg/abc.md'

console.log(path.dirname(filepath));
// /User/ddg
console.log(path.basename(filepath)); 
// abc.md
console.log(path.extname(filepath)); 
// .md

// 2、join 路径拼接
const basepath = "/User/ddg"
const filename= '/abc.md'
const joinUrl = path.join(basepath,filename)
console.log(joinUrl);// \User\ddg\abc.md

// 3、resolve 路径拼接
// 它会解析第一个参数 的 / ./ ../ ,
// / 表示这个文件地址的根磁盘
// 如果第一个参数 没有加 / ./ ../ 那么,则会拼接上 绝对路径
// 如果第一个往后的参数有 / 则会 直接返回最后一个参数的路径
const joinUrl2 = path.resolve(basepath,filename)
console.log(joinUrl2);// F:\User\ddg\abc.md

3.2 fs

const fs = require('fs')

// 读取文件的信息
const filepath = './abc.txt'

// 1、同步操作 读取文件信息
const info = fs.statSync(filepath)
// console.log('后续要执行的代码会被阻塞');
// console.log(info);

// 2、异步操作 读取文件信息
fs.stat(filepath, (err, info) => { 
         
  if(err){ 
        
    console.log(err);
    return
  }
  console.log(info);
})
// console.log('后续要执行的代码会被阻塞');

// 3、promise
fs.promises.stat(filepath).then(info=>{ 
        
  console.log(info);
}).catch((err)=>{ 
        { 
        console.log(err);}})
console.log('后续要执行的代码会被阻塞');

const fs = require('fs')

fs.open('./abc.txt', (err, fd) => { 
        
  if (err) { 
        
    console.log(err);
    return
  }
  // 通过描述符获取信息
  fs.fstat(fd, (err, info) => { 
         
    if(err){ 
        
      console.log(err);
      return
    }
    console.log(info);
  })
})

const fs = require('fs')

// 文件写入
fs.writeFile('./abc.txt','呆呆狗2',{ 
        flag:"a"},err=>{ 
        
  console.log(err);
})
/* 1、 w 打开文件写入 默认值。 会覆盖掉原先的内容 2、 w+ 打开文件进行读写,如果不存在则创建文件 3、 r+ 打开文件进行读写,如果不存在那么抛出异常 4、 r 打开文件读取,读取时的默认值 5、 a 打开要写入的文件,将流放在文件末尾。如果不存在则创建文件 6、 a+ 打开文件以进行读写,将流放在文件末尾,如果不存在则创建文件 */

// 文件读取
fs.readFile('./abc.txt',{ 
        encoding:'utf-8'},(err,data)=>{ 
        
  console.log(data);
  // 不设置 encoding:'utf-8' 就显示二进制的编码
})

const fs = require('fs')

// 1、创建文件夹
const dirname = './ddg'
if (!fs.existsSync(dirname)) { 
        
  fs.mkdir(dirname,err=>{ 
        
    console.log(err);
  })
}

// 2、读取文件夹中的所有文件
fs.readdir(dirname,(err,files)=>{ 
        
  console.log(files);// [ 'a.txt', 'b.txt' ]
})

// 3、重命名 文件
// 旧路径 新路径 回调函数
fs.rename('./ddg','./ddg2',err=>{ 
        
  console.log(err);
})

3.3 events 模块

node中的核心API 都是基于异步事件驱动的。

在这个体系中,某些对象(发射器(Emiteers))发出某一个事件

我们可以监听这个事件 (监听器 Listeners),并且传入的回调函数,这个回调函数会在监听到事件时调用

发出事件和监听事件 都是通过 EventEmitter 类 来完成的,他们都属于 events 对象

emitter.on(eventName,listener): // 监听事件,也可以使用 addListener
emitter.off(eventName,listener): // 移除事件,也可以使用 removeListener
emitter.emit(eventName[,...args]): // 发出事件,可以携带一些参数

4、包管理工具

4.1 配置文件

每一个项目都对应一个配置文件(package.json),包括项目名称、使用的插件、版本号、项目描述等等

npm init -y

4.2 配置文件常见的属性

  • scripts属性,用于配置一些脚本命令,以键值对的形式存在,配置后我们可以通过 npm run 命令的key 来执行这个命令
  • dependencies 属性 是无论开发环境还是生产环境都需要的依赖包
  • devDependencies属性 是 生产环境不需要的依赖包

4.3 版本管理的问题

比如版本 2.23.8

  • 第一个数字,表示可能不兼容之前的版本,这个版本号一般很少修改
  • 第二个数字,向下兼容的功能性新增,就是 新功能增加,但是兼容之前的版本
  • 第三个数字,前面两个没有任何修改,但是 修复了 之前的 bug

^2.23.8 表示 第一个数保持不变的, 第二个和第三个 永远安装最新的版本

~2.23.8 表示 第一个和第二个保持不变的,第三个永远安装最新的版本

5、buffer 和 浏览器的事件循环

5.1 数据的二进制

计算机追踪所有的内容:文字、数字、图片、音频、视频都终会使用二进制来表示

5.2 buffer 和二进制

对于前端来说,很少会和二进制打交道,但是对于服务器端为了做很多的功能,必须直接去操作二进制的数据

所以 node 为了 可以方便开发者完成更多功能,提供给了我们一个类 Buffer , 并且它是全局的

Buffer 看成是一个存储二进制的数组,数组中的每一项,可以保存 8位 二进制

5.3 Buffer 对字符串的存储

const message = "hello world"

// 第一种 1、创建 Buffer
// 打印出来的,是和 message 一一对应的,打印出来的 每一组数字,是 16进制的
//const buffer = new Buffer(message)
//console.log(buffer); //<Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>

// 第二种 2、
const buffer2 = Buffer.from(message)
console.log(buffer2);

5.4 Buffer 对文字的存储

const message = "呆呆狗"
// 其实 一个汉字 对应 三个字节码,
const buffer2 = Buffer.from(message)
console.log(buffer2);
// <Buffer e5 91 86 e5 91 86 e7 8b 97>

// 解码
console.log(buffer2.toString());// 呆呆狗

5.5 对 文件的处理

const fs = require('fs')

// 1、对文本文件的操作
fs.readFile("./foo.txt", { 
         encoding: 'utf-8' }, (err, data) => { 
        
  console.log(data);
  // 如果不传 utf-8 输出的,其实是 Buffer。本质上,我们读取到的东西都是二进制
})

// 2、对 图片的操作
fs.readFile('./one.png', (err, data) => { 
        
  console.log(data); // 读取到的 也是 Buffer

  // 我们可以在写入 文件
  fs.writeFile('./one_copy.png', data, err => { 
        
    // 这里的 data 表示要写入谁 就是 图片的 Buffer
    console.log(err);
  })
})

// npm i sharp 先安装依赖,然后 裁剪,然后输出
sharp('./one.png').resize(200,200).toFile('./baz.png')

6、事件循环

6.1 事件循环定义

事件循环 可以理解成 我们编写 js 代码 和 浏览器 或者 node 之间的一个桥梁

浏览器的事件循环是 一个我们编写的 js 代码和 浏览器 API 调用 的一个桥梁,桥梁之间他们通过回调函数进行沟通

node 的事件循环是一个我们编写 js 代码 和 系统调用 (file、system、network) 之间的一个桥梁,桥梁 之间他们通过回调函数进行沟通的

6.2 进程和线程

进程: 计算机已经运行的程序

线程:操作系统能够运行运算调度的最小单位

操作系统就像是一个工厂,工厂里面有很多车间,这个车间就是进程,工人就是线程

6.3 多进程多线程开发

6.4 浏览器 事件循环 面试题

setTimeout(function () { 
        
  console.log("set1");
  new Promise(function (resolve) { 
        
    resolve();
  }).then(function () { 
        
    new Promise(function (resolve) { 
        
      resolve();
    }).then(function () { 
        
      console.log("then4");
    });
    console.log("then2");
  });
});

new Promise(function (resolve) { 
        
  console.log("pr1");
  resolve();
}).then(function () { 
        
  console.log("then1");
});

setTimeout(function () { 
        
  console.log("set2");
});

console.log(2);

queueMicrotask(() => { 
        
  console.log("queueMicrotask1")
});

new Promise(function (resolve) { 
        
  resolve();
}).then(function () { 
        
  console.log("then3");
});

// pr1
// 2
// then1
// queuemicrotask1
// then3
// set1
// then2
// then4
// set2

分析:

  1. 先输出 pr1 , then1 进入 微任务队列
  2. 输出 2 , queueMicrotask 创建一个微任务
  3. then3 加入微任务
  4. 主线程 执行完毕,执行 第一波微任务 依次输出 then1,queueMicrotask,then3,此时已经没有微任务了,继续执行下一个宏任务
  5. 第一个定时器, 输出 set1 ,把 第一个定时器的 then 加入微任务队列
  6. 输出 then2
  7. 这一次的宏任务执行完毕,继续执行这一次的微任务,输出 then4
  8. 执行第二个定时器

async function async1 () { 
        
  console.log('async1 start')
  await async2();
  console.log('async1 end')
}
 
async function async2 () { 
        
  console.log('async2')
}

console.log('script start')

setTimeout(function () { 
        
  console.log('setTimeout')
}, 0)
 
async1();
 
new Promise (function (resolve) { 
        
  console.log('promise1')
  resolve();
}).then (function () { 
        
  console.log('promise2')
})

console.log( 

标签: express连接器mb

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台