新版第五阶段Vue前置知识
1)ES6模块化与异步编程高级
回顾:
node.js中遵循CommonJS模块化规范,
导入模块用require()方法,
对外共享用module.exports对象。
const fs = require('fs')
module.exports = {
nickname:'zhangsan',
//注意下面的方法不用打function 和es6规定的类一样
sayHello() {
console.log('hello!')
}
}
ES6语法
ES6统一后的JS书写规范:
导入用 import from
向外共享用 export
import m1 from './index.js'
export default {
a,
b,
show
}
node中默认仅支持CommonJS模块化规范,要体验ES6语法:
1 .安装14.15.1以上版本
2 .在package.json根节点中添加"type":"module"
节点
在项目中执行 npm init -y
之后就会有package.json包配置管理文件。
1 默认导出语法:其中a,b为变量,show为方法。一个模块中只能有一个默认导出。可以没有但是不能多于一个。
export default {
a,
b,
show //show是一个方法
}
2 默认导入语法:这里m1 为自定义导入的名字,可以更改。
import m1 from './index.js'
3 按需导出:可以使用多次。
export let s1 = 10
export function say(){}
4 按需导入:
import {s1} form '模块标识符'
按需导入导出注意事项:
1 每个模块中可以使用多次按需导出
2 按需导入的成员名称必须和按需导出的名称一致
3 按需导入时可以使用as关键字 进行重命名
4按需导入可以和默认导入一起使用
默认导入与按需导入可以同时存在:
import info,{s1 ,s2 as ss2,say} form './m1.js'
此处 s2 被重命名为ss2 ,不能再用s2 来访问。
import info form './m1.js'
这里的 info 接收 ./m1.js 文件中的 默认 导出部分。
直接执行代码,获取结果,并不接收模块成员:
for (let i=0;i<3;i++){
console.log(i)
}
//在接收的模块中写
import './m1.js'
省略了对象,就是直接获取代码结果。
Promise
ES6新增,解决回调地狱相互嵌套问题。
是一个构造函数,
可以创建promise的实例,const p = new Promise()
,
new出来的实例对象,代表一个异步操作。
支持链式调用,
原型上包含一个then方法。
pormise对象用来封装一个异步操作并可以获取成功/失败的结果值。
.then()方法用于预先指定成功和失败的回调函数
p.then(result=>{},error={})
p.then(成功的回调函数,失败的回调函数)
成功回调必选,失败回调可选。
.catch() 用于捕获链式操作中的错误,如果catch写在最后,那么整个代码块中出现一次错误,出错后面的代码都不执行。
如果想让出错的地方报错后下面代码还执行,那就把catch提到相应位置,不要放在最后。
node.js官方提供的 fs 模块仅支持以回调函数的方式读取文件,不支持promise的调用方式。
then-fs模块支持以promise的方式读取文件内容。
基本使用:
import thenFs from 'then-fs'
thenFs.readFile('./files/1.txt','utf-8').then(r1 =>{console.log(r1)},err1 => {console.log(err1.message)})
import thenFs from 'then-fs'
thenFs.readFile('./files/1.txt','utf-8')
.catch((err)=>{
console.log(err.message)
})
.then((r1)=>{
console.log(r1)
//注意 此处使用了return,代码执行后会把一个新的thenFs对象返回
//thenFs对象执行后返回promise,所以后续可以使用.then把代码继续下去
return thenFs.readFile('./files/2.txt','utf-8')
})
.then((r2)=>{
console.log(r2)
return thenFs.readFile('./files/3.txt','utf-8')
})
.then((r3)=>{
console.log(r3)
})
.all()
方法会发起并行的 Promise 异步操作,等所有的异步操作全部结束后才会执行下一步的 .then 操作(等待机制)。
注意:此处数组中的顺序就是下面r1r2r3拿到的顺序
示例代码如下:
import thenFs from 'then-fs'
const promiseArr = [
thenFs.readFile('./files/1.txt', 'utf8'),
thenFs.readFile('./files/22.txt', 'utf8'),
thenFs.readFile('./files/3.txt', 'utf8'),
]
Promise.all(promiseArr).then(([r1,r2,r3]) => {
console.log(r1)
console.log(r2)
console.log(r3)
})
.catch((err)=>{
console.log(err)
})
.race()
Promise.race() 方法会发起并行的 Promise 异步操作,只要任何一个异步操作完成,就立即执行下一步的.then 操作(相当于一个赛跑机制)
import thenFs from 'then-fs'
const promiseArr = [
thenFs.readFile('./files/1.txt', 'utf8'),
thenFs.readFile('./files/2.txt', 'utf8'),
thenFs.readFile('./files/3.txt', 'utf8'),
]
Promise.race(promiseArr).then((result) => {
console.log(result)
})
.catch((err)=>{
console.log(err)
})
//结果为一个111 或者 一个222 或者一个333
基于promise封装异步读取文件的方法
封装自己的读文件方法,要求:
1 名称为getFile
2 方法接收一个形参fpath 表示读取文件的路径
3 方法的返回值为promise
想要创建具体的异步操作,需要再new promise()期间,传递一个function函数,将具体操作定义到函数内部。
import fs from 'fs'
function getFile(fpath) {
return new Promise(function (resolve, reject) {
fs.readFile(fpath, 'utf-8', (err, dataStr) => {
if (err) return reject(err)
resolve(dataStr)
})
})
}
getFile('./files/11.txt').then((r1) => { console.log(r1) }, (err) => { console.log(err.message) })
获取.then的两个实参
通过then指定的两个函数,被function的形参接收。
async/await
ES8引入的新语法,用来简化promise异步操作。在此出现前只能用then方法处理。示例代码如下:
import thenFs from 'then-fs'
thenFs.readFile('./files/1.txt', 'utf-8')
.then(r1 => {
console.log(r1)
return thenFs.readFile('./files/2.txt', 'utf-8')
})
.then(r2=>{
console.log(r2)
return thenFs.readFile("./files/3.txt",'utf-8')
})
.then(r3=>{
console.log(r3)
})
有then之后解决了回调地狱问题。但是代码冗余阅读性差。
有了await之后,不再获取某个方法返回值的promise对象,而是获取最后的值。
async function getAllfile(){
const r1 = await thenFs.readFile('./files/1.txt','utf8')
console.log(r1)
const r2 = await thenFs.readFile('./files/2.txt','utf8')
console.log(r2)
const r3 = await thenFs.readFile('./files/3.txt','utf8')
console.log(r3)
}
getAllfile()
函数内部用了await,外面必须用async来修饰
async方法中,第一个await之前的代码同步执行,后面的异步执行。但是如果在这个async/await函数之外的代码还是要顺序执行。顺序执行完了再回这个函数里面执行函数剩下的代码。
promise补充资料
Promise 是一个对象,对象里存储一个状态,这个状态是可以随着内部的执行转化的,为以下三种状态之一:等待态(Pending)、完成态(Fulfilled)、拒绝态(Rejected)。
一开始,我们先设置好等状态从 pending 变成 fulfilled 和 rejected 的预案(当成功后我们做什么,失败时我们做什么)。
Promise 启动之后,当满足成功的条件时我们让状态从 pending 变成 fullfilled (执行 resolve);当满足失败的条件,我们让状态从 pending 变成 rejected(执行 reject)
Eventloop
关于同步任务与异步任务。
js是一门单线程语言,同时只能执行一个任务。遇到某个耗时任务将会导致程序假死。
为了防止某个耗时任务导致程序假死的问题,JavaScript 把待执行的任务分为了两类:
- 同步任务(synchronous)又叫做非耗时任务,指的是在主线程上排队执行的那些任务。只有前一个任务执行完毕,才能执行后一个任务。
- 异步任务(asynchronous)又叫做耗时任务,异步任务由 JavaScript 委托给宿主环境进行执行当异步任务执行完成后,会通知 JavaScript 主线程执行异步任务的回调函数。
注意此处宿主环境指:chrome环境中为chrome,node环境中为node.
执行栈里面的任务被情况的时候就去任务队列里找可以执行的任务。
宏任务与微任务
js进一步把异步任务,分为宏任务与微任务(macrotask microtask)
宏任务:异步ajax请求、setTimeout、setInterval、文件操作、其他宏任务
微任务:promise.then .catch .finally和其他微任务
注意:promise后面的function是同步任务,不是异步任务。.then才是异步微任务。
每执行一个宏任务都要查询是否存在微任务,微任务优先。