nodeES6模块化 + Promise(ES6新对象) +async和await(ES2017关键字) 5+JS执行机制(事件循环)
2022/2/10 22:13:58
本文主要是介绍nodeES6模块化 + Promise(ES6新对象) +async和await(ES2017关键字) 5+JS执行机制(事件循环),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
node学习总结2
- nodeES6模块化
- Promise(ES6新对象)
- async和await(ES2017关键字)
- async和await读取JSON文件案例
- JS执行机制(事件循环)
- 微任务和宏任务
1. ES6模块化
1.1 CommonJS 规范
node.js 遵循了 CommonJS 的模块化规范。其中:
- 导入其它模块使用 require()方法
- 模块对外共享成员使用 module.exports 对象
1.2 模块化开发好处
模块化开发的好处有很多,其中:
- 实现了在JS文件中引用其他文件
- 避免命名冲突的问题
- 大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用
- 只需关心当前模块本身的功能开发,需要其他模块的支持时,在模块内调用目标模块即可
1.3 模块化规范划分
在 ES6 模块化规范诞生之前,JavaScript 社区已经尝试并提出了 AMD 、 CMD 、 CommonJS 等模块化规范。
但是,这些由社区提出的模块化标准,还是存在一定的差异性与局限性、并不是浏览器与服务器通用的模块化标准
- AMD 和 CMD 适用于浏览器端的 Javascript 模块化
- CommonJS 适用于服务器端的 Javascript
模块化太多的模块化规范给开发者增加了学习的难度与开发的成本。因此,官方的 ES6 模块化规范诞生了!
1.4 ES6模块化开发注意点
node.js 中默认仅支持 CommonJS 模块化规范,若想基于 node.js 体验与学习 ES6 的模块化语法,需要按照如下两个步骤进行配置:
- 确保安装了 v13.0.0 或更高版本的 node.js
- 在 package.json 的根节点中添加 “type”: “module” 节点
- 配置之后,则只能使用ES6模块化语法,不能再使用CommonJS语法了
1.5 ES6 导入导出
三种方式:1.导入导出缺省的对象.2.按需导入导出2.仅导入导出逻辑
a.js文件:
// // 创建文件夹: 注意别有特殊符号和汉字 // // 初始化: npm init -y // // 导入方法1 - 前缀后缀不能省略; // // default导出的数据,不能解构; // import obj from './02-b.js'; // console.log(obj); // obj.c(); // 导入方法2 - 前缀后缀不能省略; // 按需导出的数据,必须解构导入 import { d, e, f as fn } from './02-b.js'; console.log(d, e); fn(); // // 导入方法3 - 只导入,不接收; // import './02-b.js'
b.js文件:
// // 导出方法1 // // default导出,不能解构; // export default { // a: 1, // b: 2, // c: () => console.log('我是函数c') // } // 导出方法2 - 按需导出 // 必须以解构的方式接收 export let d = 3; export const e = 4; export function f() { console.log('我是函数f'); } // // 第三种导出,一般使用的是逻辑,不是导出的具体值 // console.log('忽有故人人上过,回首山河已是秋。他朝若是同淋雪,此生也算共白头。');
2.Promise对象
异步操作是 JavaScript 编程的麻烦事,麻烦到一直有人提出各种各样的方案,试图解决这个问题。早期使用回调函数处理异步编码,但存在回调地狱的问题。ES6中,新增了Promise 对象,从此异步编程摆脱了回调函数的束缚。
2.1 使用语法
let p = new Promise((resolve, reject) => { // ... some code if (/* 异步操作成功 */) { resolve(value); } else { reject(error); } });
注意点:
- new Promise()
- 必须传入一个函数作为Promise的参数,这个函数在 new Promise的时候就会执行
- 函数有 resolve 和 reject 两个形参
- 函数就相当于一个容器,可以将异步任务放到这里
- 将异步任务成功的结果传给 resolve 函数;将失败的信息传给 reject 函数
p.then( result => { /* 获取成功的结果 */ } ); // 或者 p.then( result => { /* 获取成功的结果 */ }, err => { /* 获取失败的结果 */ } ); // 或者 p.then( result => { /* 获取成功的结果 */ } ).catch( err => { /* 获取失败的结果 */ } );
注意点:
- then方法接收以个函数类型的参数,只处理成功
- then方法接收两个函数类型的参数,分别用于接收 resolve 的值 和 reject 的值
- then方法也可以只接收一个参数,表示只接收 resolve 的值,失败的结果可以通过链式调用catch方法捕获
2.2 Promise中的同步异步
new Promise 和 new 其他对象一样,是同步任务。
获取结果时(调用 resolve 触发 then方法时)是异步的。
2.3 使用Promise解决回调地狱
代码略;
2.4 Promise 封装
// 封装 function myReadFile(filename) { return new Promise((resolve, reject) => { fs.readFile(filename, 'utf-8', (err, data) => { err ? reject(err) : resolve(data.length); }) }); } // 调用 myReadFile('./files/a.txt') .then(a => { console.log(a); return myReadFile('./files/b.txt'); }) .then(b => { console.log(b); return myReadFile('./files/c.txt'); }) .then(c => { console.log(c) })
2.4 第三方then-fs解决回调地狱
// npm i then-fs const fs = require('then-fs'); fs.readFile('./files/a.txt', 'utf-8') .then(res1 => { console.log(res1); return fs.readFile('./files/b.txt', 'utf-8') }) .then(res2 => { console.log(res2); return fs.readFile('./files/b.txt', 'utf-8') }) .then(res3 => { console.log(res3) })
注意:未来很多模块支持Promise对象开发,就是返回的是一个Promise对象; 如 axios
3. async 和 await 关键字
async 和 await 是 ES2017 中提出来的,async 和 await 两个关键字的出现,简化的 Promise 的使用。
3.1 async 关键字
async关键字使用比较简单,所以 async 的使用注意以下三点即可 :
- async 用于修饰一个 function
- async 修饰的函数,总是返回一个 Promise 对象
- 函数内的所有值,将自动包装在 resolved 的 promise 中
3.2 await关键字
await关键字比较繁琐,注意点比较多。首先,await 只能出现在 async 函数内,await 让 JS 引擎等待直到promise完成并返回结果,语法:
let value = await promise对象; // 等待promise对象的结果,然后将结果赋值给 value
由于await需要等待promise执行完毕,所以 await会 暂停函数的执行,但不会影响其他同步任务。
所以,await总结如下四点:
- await只能出现在异步函数中!
- await能停止代码执行,让后面的同步代码,先执行;
- await后面跟随的是一个promise对象;
- await返回的是: Promise对象中的then()中的回调函数中的参数res;
3.3 async 和 await 解决回调地狱
// async 和 await 解决回调地狱也要用到 then-fs ,因为他直接返回 Promise 对象; // 导入 then-fs import thenFs from 'then-fs'; // await 一定要出现在异步函数中 async function fn() { let str1 = await thenFs.readFile('./txt/a.txt', 'utf8'); console.log(str1); let str2 = await thenFs.readFile('./txt/b.txt', 'utf8'); console.log(str2); let str3 = await thenFs.readFile('./txt/c.txt', 'utf8'); console.log(str3); } // 调用函数 fn();
5.JS执行机制(事件循环)
- js代码开始执行后,主线程执行栈中会把任务分为两类.
- 一类是同步任务, 一类是异步任务; 主线程执行栈优先执行同步任务,
- 异步任务会被放入特定的处理程序中,满足条件后,被放到消息(任务/事件)队列中,
- 主线程执行栈中所有的同步任务执行完毕之后,通过事件循环去消息(任务/事件)队列中,
- 挑选优先满足条件的程序,放入主线程执行栈中执行。事件循环,周而复始,一直执行。
6.微任务和宏任务
在ES3 以及以前的版本中,JavaScript本身没有发起异步请求的能力,也就没有微任务的存在。在ES5之后,JavaScript引入了Promise,这样,不需要浏览器,JavaScript引擎自身也能够发起异步任务了。
Tick会触发浏览器渲染,Promise不会触发,所以更加轻量级,多使用;
6.1 宏任务
(macro)task,可以理解是每次执行栈执行的代码就是一个宏任务
- 主线程上的执行栈中所有的代码块
- setTimeout
- setInterval
- Ajax
- 事件
6.2 微任务
微任务(microtask)是宏任务中的一个部分,它的执行时机是在同步代码执行之后,下一个宏任务执行之前。总结起来,微任务有:
- Promise.then
- process.nextTick(Node.js 环境)
6.3 宏任务和微任务执行机制
JS优先执行同步任务,然后执行微任务,最后执行宏任务。
总结:Promise中的then()比大部分异步代码,优先执行!
这篇关于nodeES6模块化 + Promise(ES6新对象) +async和await(ES2017关键字) 5+JS执行机制(事件循环)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-16Vue3资料:新手入门必读教程
- 2024-11-16Vue3资料:新手入门全面指南
- 2024-11-16Vue资料:新手入门完全指南
- 2024-11-16Vue项目实战:新手入门指南
- 2024-11-16React Hooks之useEffect案例详解
- 2024-11-16useRef案例详解:React中的useRef使用教程
- 2024-11-16React Hooks之useState案例详解
- 2024-11-16Vue入门指南:从零开始搭建第一个Vue项目
- 2024-11-16Vue3学习:新手入门教程与实践指南
- 2024-11-16Vue3学习:从入门到初级实战教程