Node中的模块化
node.js 遵循了 CommonJS 的模块化规范。其中:
导入其它模块使用 require()方法
模块对外共享成员使用 module.exports 对象
ES6模块化规范 es6 模块化也是优先从缓存中加载
每个 js 文件都是一个独立的模块
导入其它模块成员使用 import 关键字
向外共享模块成员使用 export 关键字
ES6模块化语法 – 默认导入导出 package.json 文件中必须要有"type": "module",
默认导出的语法: export default 默认导出的成员
默认导入的语法: import 接收名称 from '模块路径'
package.json 文件中必须要有"type": "module",
ES6模块化语法 – 按需导入与按需导出
按需导出的语法: export const s1 = 10
按需导入的语法: import { 按需导入的名称 } from '模块路径'
ES6模块化语法 –直接导入模块(无导出)
如果只想单纯地执行某个模块中的代码,并不需要得到模块中向外共享的成员。
此时,可以直接导入并执行模块代码,语法:import '模块的路径'
注意点:
导入JS文件,为了让JS代码执行一次
Vue 中,这种语法还可以导入 css、less等文件
promise
1:promise 用于解决异步函数嵌套的问题 是一个构造函数 需要new进行创建实例
2:promise 构造函数的形参接收的是一个函数 函数里面一定 要放入异步函数
3 :promise 形参的函数 有两个形参 一个是处理成功的结果 一个是处理失败的结果
4:Promise 的then( )和Cath( )可以处理成功和失败的结果 里面也是一个函数
例子:
// 导入fs 模块
import fs from 'fs' // 默认导入
// 1 promise 是一个构造函数 需要new进行创建实例
// 2 一般喜欢叫创建出的实例 为promise对象
// 3 promise 构造函数的形参接收的是一个函数 函数里面一定 要放入异步代码
let p1 =new Promise((resolve,reject)=>{ // 箭头函数里面的形参第一个是成功 第二个是失败
fs.readFile('./tex/a.txt','utf-8',(err,data)=>{
// 判断读取结果是否成功
if(err){
reject(err) //失败的
}else{
resolve(data) // 成功的
}
})
})
// 处理结果方法1
p1.then(
result => console.log(result), //第一个函数处理成功
error => console.log('读取文件失败:'+error.message) //第二函数处理失败
)
// 处理结果方法2 (重点掌握)
p1.then(result => console.log(result))
.catch(error=>console.log(error.message))
then方法的链式调用
new Promise((resolve, reject) => {
resolve(1);
}).then(r1 => {
console.log(r1); // 1
return new Promise( /* resolve(2); 其他代码略 */ )
}).then(r2 => {
console.log( r2 ); // 2
})
then-fs模块解决回调地狱
// 下载 then-fs:npm i then-fs
// 导入 模块
import thenFs from 'then-fs'
// 利用 then-fs 模块解决回调地狱
thenFs.readFile('./tex/a.txt','utf8').then(res=>{
console.log(res)
return thenFs.readFile('./tex/b.txt','utf8')
}).then(res=>{
console.log(res)
return thenFs.readFile('./tex/c.txt','utf8')
}).then(res=>{
console.log(res)
})
Promise对象的同步异步
new Promise 的参数中的代码是同步执行
then 及 catch中的代码是异步执行
// 同步先执行 异步后执行
console.log(1)
new Promise((resolve,reject)=>{
console.log(2)
resolve()
console.log(3)
}).then(res=>{
console.log(4)
})
console.log(5)
// Promise 的构造函数中 和then catch 中的同步异步问题
// 12354
// new Promise 的参数中的代码是同步执行
// then 及 catch中的代码是异步执行
async 和 await 修饰符
async关键字
// 1.async 修饰的函数,总是返回一个 Promise 对象
async function fn(){
console.log('我是fn函数')
// 2.函数的返回值,将自动包装在 resolve 的 promise 中
return 123
}
// 调用 注意 async 修饰符 不是异步函数
let result = fn()
// console.log(result)
// 证明async函数中return返回的数据 是被 promise 对象中resolve()抛出的数据
result.then(res=>console.log(res))
await关键字
// 定义一个async修饰的函数
async function getPromise(){
return '乖乖'
}
// 1.await只能出现在async修饰的函数中!
async function fn(){
// 2.await后面跟随的是一个promise对象;
// 4.await返回的是: Promise对象中的then()中的回调函数中的参数res;
let str = await getPromise()
console.log(str)
console.log(123)
}
// 在这一句代码之前调用
fn()
// 3.await能停止代码执行,让后面的同步代码,先执行;
console.log('梦迪迪')
async和await解决回调地狱问题
// 导入then-fs模块
import thenFs from 'then-fs'
// 定义一个函数 用async修饰 将来方便使用 await 关键字
async function fn (){
let str1 = await thenFs.readFile('./tex/a.txt','utf8')
console.log(str1)
let str2 = await thenFs.readFile('./tex/b.txt','utf8')
console.log(str2)
let str3 = await thenFs.readFile('./tex/c.txt','utf8')
console.log(str3)
}
fn()
try和catch关键字
try catch 可以捕获错误 finally 一定执行
// 导入then-fs
import thenFs from "then-fs";
// 定义一个函数 用async 修饰 将来方便使用 await 关键字
async function fn(){ //try catch 可以捕获错误 finally 一定执行
try{
let str1= await thenFs.readFile('./tex/a.txt','utf8')
console.log(str1)
let str2= await thenFs.readFile('./tex/b.txt','utf8')
console.log(str2)
let str3= await thenFs.readFile('./tex/c.txt','utf8')
console.log(str3)
}catch(e){
console.log(e.massage)
}finally{
console.log('执行完毕')
}
}
fn()
案例:文件操作增删改查
// 利用async 和await 及 then-fs 封装增删改查
// 封装好的方法要返回数据
import thenFs from 'then-fs'
// es6模块化下 无法使用——dirname 所以使用相对路径
let url = './data.json'
// 按需导出
// 1 查询
export async function getData() {
try {
// 利用thenFs模块读取文件 转换为数组 返回
let str = await thenFs.readFile(url, 'utf8')
// 转换为数组 并返回
let arr = JSON.parse(str)
return arr
} catch (e) {
return ('获取失败')
}
}
// 测试
/* getData().then(res=>{
console.log(res)
}) */
// 2 添加
export async function addData(obj) {
// 读取数据转换为数组
let arr = await getData()
// 向数组中添加元素 obj中添加id
obj.id = arr[arr.length - 1].id * 1 + 1
arr.push(obj)
// 写入代码需要 try捕获错误
try {
await thenFs.writeFile(url, JSON.stringify(arr))
return ('添加成功!')
} catch (e) {
return ('添加失败!')
}
}
// 测试
/* addData({
"bookname": "毛德洋",
"author": "梦迪迪",
"publisher": "深圳人民出版社"
}).then(res=>{
console.log(res)
}) */
// 3删除
export async function delData(id) {
// 读取数据转换为数组
let arr = await getData()
// 过滤
let newArr = arr.filter(item => item.id != id)
// 写入
try {
await thenFs.writeFile(url, JSON.stringify(newArr))
return ('删除成功!')
} catch (e) {
return ('删除失败!')
}
}
/* // 测试
delData(5).then(res => {
console.log(res)
})
*/
// 4 修改
export async function putData(obj) {
// 读取数据转换为数组
let arr = await getData()
// 修改删除在添加
let index = arr.findIndex(item => item.id == obj.id)
arr.splice(index, 1, obj)
try {
await thenFs.writeFile(url, JSON.stringify(arr))
return ('修改成功!')
} catch (e) {
return ('修改失败!')
}
}
// 测试
putData({
"id": 4,
"bookname": "毛德洋",
"author": "梦迪迪",
"publisher": "中国人民出版社"
}).then(res => {
console.log(res)
})
// 默认导出
export default {
getData,
addData,
delData,
putData
}
[
{
"id": 1,
"bookname": "三国演义",
"author": "罗贯中",
"publisher": "武汉人民出版社"
},
{
"id": 2,
"bookname": "水浒传",
"author": "施耐庵",
"publisher": "北京人民出版社"
},
{
"id": 3,
"bookname": "红楼梦",
"author": "曹雪芹",
"publisher": "铁岭人民出版社"
},
{
"id": 4,
"bookname": "毛德洋",
"author": "梦迪迪",
"publisher": "中国人民出版社"
}
]
JS代码执行机制
js代码开始执行后,主线程执行栈中会把任务分为两类.
一类是同步任务, 一类是异步任务; 主线程执行栈优先执行同步任务,
异步任务会被放入特定的处理程序中,满足条件后,被放到消息(任务/事件)队列中,
主线程执行栈中所有的同步任务执行完毕之后,通过事件循环去消息(任务/事件)队列中,
挑选优先满足条件的程序,放入主线程执行栈中执行。事件循环,周而复始,一直执行。
宏任务和微任务
Tick会触发浏览器渲染,Promise不会触发,所以更加轻量级,多使用
宏任务
(macro)task,可以理解是每次执行栈执行的代码就是一个宏任务
主线程上的执行栈中的代码
每次从事件队列中获取一个事件回调并放到执行栈中执行。
比如去银行排队办业务,每个人的业务就相当于是一个宏任务;
总结起来,宏任务有
setTimeout
setInterval
Ajax
事件
微任务
微任务(microtask)是宏任务中的一个部分,它的执行时机是在同步代码执行之后,下一个宏任务执行之前。
总结起来,微任务有:
Promise.then
process.nextTick(Node.js 环境)
Mac 查自己的ip的地址是 ifconfig