一、js中的错误处理
js是一种单线程的语言,如果程序中某一个位置出现了语法错误,则程序之后的代码无法执行
如果想要让程序在报错之后还能继续向下执行,则需要使用try…catch语法进行捕获错误消息。
如果在try当中的语句发生了语法错误,将错误消息使用catch捕获,后续代码还可以继续运行。
try中可以捕获的错误类型:TypeError(数据类型报错)、RangeError(范围错误)以及throw抛出的错误,但是不能捕获SyntaxError(语法错误)。
//数据类型错误
try{
//try中存入有可能会出现的错误代码(写入文件、连接数据库、操作数据库)
//在try当中,如果有哪一句话发生了错误,则后面的语句将不会执行
//类型错误
const aa = 100;
console.log(aa());
...
}catch(e){
//catch方法需要传入一个参数e,这个参数表示错误对象
//错误对象,可以通过console.dir的方法查看对象结构
//错误对象中有两个属性:message(错误消息)和stack(错误跟踪,精确到行列)
console.dir(e);//e表示错误对象
console.log(e);//TypeError: aa is not a function
}
//try...catch后面的代码仍然会执行
//范围错误
try {
let arr = new Array(-1);
console.log(arr);
} catch (e) {
console.log(e);//RangeError: Invalid array length
}
//throw手动抛出异常方式一
try {
throw ('throw抛出异常方式一');//throw抛出异常方式一
} catch (e) {
console.log(e);
}
//throw手动抛出异常方式二
try {
throw new Error('throw抛出异常');//Error: throw抛出异常方式二
throw new TypeError('抛出一个类型错误');//TypeError: 抛出一个类型错误
throw new RangeError('抛出一个范围错误');//RangeError: 抛出一个范围错误
} catch (e) {
console.log(e);
}
二、Promise是什么
Promise是JS中进行异步编程的新的解决方案。
Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值,
Promise可以避免回调地狱,通过使用then方法避免无限嵌套。
回调地狱是指:存在异步任务的代码,不能保证能按照顺序执行,所以只能以嵌套的方式保证先执行A,再执行B
异步是什么?
异步是指同一时间内可以干多件事,且每件事不会互相影响, 带有回调函数的都是明显的异步。
【举例】定时器、fs模块读写文件、数据库操作、ajax…)
【场景】注册时用户名重复,鼠标失焦时就已经可以检测出来结果
二、Promise初体验
1、Promise本质是一个构造函数(产生一个实例化对象);
2、Promise构造函数,语法规定,必须要传一个回调函数——executor 执行器函数;
3、executor执行器函数,通常执行异步代码(定时器、文件操作、数据库操作、ajax);
3、Promise构造函数中执行器函数中还需要传递两个参数,且这两个参数仍然是回调函数,
这两个回调函数名基本不会改变:resolve(当前状态是成功的) 和 reject (当前状态是失败的)
4、Promise主要是为了实现异步编程(定时器\fs(文件写入读取删除)\ajax\数据库)中提供成功/失败的结果;
5、Promise实例化对象有三个状态:pending等待中、fulfilled成功、rejected失败
6、Promise是通过实例化对象的三个不同的状态来控制异步编程的功能,
如果是 fulfilled状态,就执行then方法的第一个回调;
如果是rejected状态,就执行then方法的第二个回调;
如果是pending状态,就不会执行then的两个回调;
7、executor 执行器函数中的两个形式参数(resolve/reject)也是可选参数,可加可不加。
8、什么情况下会添加?当想要改变Promise实例化对象的状态的时候 需要添加,默认是pending,
可以从pending修改成fulfilled,也可以从pending修改成rejected,
但是不能从fulfilled修改成rejected,也不能从rejected修改成fulfilled,
原因是Promise实例化对象的状态只能修改一次!
let p1 = new Promise(resolve,reject) => {
resolve('ok');
//这个回调函数的作用是将Promise实例化对象的状态从pending修改成fulfilled
//状态值(PromiseResult是当下这个resolve方法的实参)
reject('error');
//reject这个回调函数的作用,就是将Promise实例化对象从pending修改成rejected
//状态值(PromiseResult是当下这个reject方法的实参)
})
//then方法是在Promise.prototype属性之中(公共方法,节约内存),所以不放在实例化对象身上
//任何一个构造函数的prototype都指向一个Object类型的实例化对象
//then方法中的回调函数可以完全不传递,也可以只传递一个
//then方法的第一个参数是当p1这个实例化对象的状态为fulfilled的时候执行的回调函数
//then方法的第二个参数是当p1这个实例化对象的状态为rejected的时候会执行的回调函数
//then中的两个回调函数执行到底执行哪一个,取决于当下p1的状态到底是fulfilled还是rejected
//resolve方法的实参('ok') 对标 then的第一个回调函数中的形参(value)
//reject方法的实参('error') 对标 then的第二个回调函数中的形参(reason)
p1.then((value)=>{
console.log('成功',value);
},(reason)=>{
console.log('失败',reason);
});
//then方法中:第一个参数是resolve方法的函数本体,第二个参数是reject方法的函数本体(函数定义)
二、利用Promise实现随机抽奖
<button>点击抽奖</button>
<script>
function myRandom(min , max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
// console.log(myRandom(1,5));
let btn = document.querySelector('button');
btn.onclick = function () {
new Promise((resolve,reject)=>{
setTimeout(()=>{
let res = myRandom(1,100);
if(res >= 30) {
resolve(res);
} else {
reject(res);
}
},2000);
}).then((value)=>{
console.log('抽奖成功,中奖数字是',value);
},(reason)=>{
console.log('未抽中');
})
}
</script>
四、利用Promise实现文件读取
//Step1:
//Step2:创建Promise实例化对象,用来表示读取文件的状态是成功还是失败
promisify
//Step1:导包
const fs = require('fs');
const { promisify } = require('util');
//Step2:调用promisify方法
//promisify方法中需要传入一个回调函数中是错误对象为优先的方法名
const myreadfile = promisify(fs.readFile)
//console.log(myReadFile);//[Function: readFile],返回一个函数
//console.log(myReadFile(__dirname + '/03.文件读取/1.txt'));//Promise{<pending>}
//Step3:调用函数
//调用函数的目的就是为了知道这个方法的返回值是Promise对象
myreadFile('文件路径').then(value=>{
value.toString()
},reason=>{
console.log(reason);
})
还用文件中的stat方法
Promise对象下的独立方法—then方法
Promise实例化对象调用Promise原型属性身上的then方法也有返回值,返回一个新的promise对象。
let p1 = new Promise((resolve,reject)=>{
resolve('ok');
})
Q1:有无返回值,
Q2:返回值是否是一个promise,
Q3:是否抛出异常
p2的状态取决于p1的then方法中的两条路,·只要选择的路中,没有throw,且返回的是非promise对象,其他状态都是fulfilled
Promise实例化对象可以调用多次
终止Promise的链式调用
Promise的链式调用就是指,一个对象下可以反复调用相同的方法/不同的方法多次。
终止Promise调用,就是在想要终止的地方,返回一个新的pendding状态的Promise对象,既不是成功也不是失败。所以不会继续执行下去。return new Promise(()=>{})
【注】Promise的用途主要是为了实现一些异步任务,当这些异步任务的结果还没有返回,Promise实例化对象的状态仍然是pedding。
Promise对象下的独立方法—catch方法
catch方法的功能是专门用来 指定失败 的回调函数,
let p1 = new Promise((resolve,reject)=>{
resolve();
})
//catch方法既可以单独使用,也可以和then方法连用
p1.then(value=>{
console.log(value)
}).catch(reason=>{
})
p1.catch()
//当then方法和catch方法连用,且then方法中也有失败的回调函数,是否还会继续执行catch方法,取决于then方法返回的新的Promise实例化对象的状态是否是失败的,因为catch是专门用来指定失败的
//如果是失败的则会执行catch,反之不会
//catch的返回值的用法和then是一样的,返回的也是一个Promise实例化对象
//只要状态回调函数中,没有返回值,则其状态就是fulfilled
Promise对象下的独立方法—resolve&reject
除了then、catch、finally三个方法之外的所有方法都放到了Promise构造函数对象本身
resolve方法返回的也是一个新的Promise实例化对象,
resolve方法的作用是:创建一个成功状态的Promise实例化对象,
//情况一:如果resolve方法传递的是非Promise
let p1 = Promise.resolve(100)
//情况二:当resolve方法传递的是Promise实例化对象的时候,p2的状态和结果完全取决于resolve方法的参数中Promise
reject方法的作用是:始终返回一个失败状态的Promise实例化对象,
reject结果值仍然是reject这个方法的实际参数值
let p1 = resolve.reject()
Promise对象下的独立方法—all
all方法是针对多个Promise实例化对象,
all方法需要传递一个参数,参数类型是数组,数组中放的的Promise实例化对象
all方法返回的是一个Promise对象,结果值取决于all方法的数组参数中所有的Promise对象的状态
当数组中每一个Promise实例化对象的状态都是成功的,则arr返回的新的Promise对象的状态也是成功的;结果值是all方法参数数组中每一个Promise实例化对象的结果值组成的数组
如果数组中的任意一个Promise实例化对象是失败的状态,则arr这个新的Promise对象的状态也是失败的,结果值将是发现的第一个失败的Promise对象的结果值。
all今后可能会被用到请求ajax/读取文件
all方法是当数组中每一个Promise实例化对象都是
let arr = Promsie.all([p1,p2,p3]);//arr是一个Promise实例化对象
arr.then(value=>{
//value是一个数组
}.reason=>{
})
Promise对象下的独立方法—race
race方法也需要传递一个数组的参数,数组中存放的仍然是Promise实例化对象,
只要是数组中任意一个Promise实例化对象的状态优先被改变了,则arr的状态和结果值
race方法需要看哪一个Promise实例化对象的状态不再是pendding了,不管是fulfilled还是rejected,只要是修改了则修改的
Promise对象下的独立方法—allSettled
allSettled方法也需要传递一个数组作为参数,
返回的也是一个Promise实例化对象,其中包含两个状态,fulfilled和rejected
不关心成功/失败,得到的结果既有fulfilled也有 最后过滤
Promise对象下的独立方法—any
any方法也需要传递一个参数,参数也是数组,数组中的内容是Promise实例化对象,
只要是这个数组中有一个Promise实例化对象的状态是fulfilled,则any返回的是fulfilled
数组中的每一个Promise对象的状态都是rejected时,则any返回的是rejected
Promise对象下的独立方法—finally
finally方法中的回调函数是不接受参数的,
不管Promise实例化对象的状态是成功还是失败,都会在最后执行finally
finallu也可以直接单独使用,主要看对象的状态是成功还是失败,但是不能是pendding
p1.catch(value=>{
resolve('success');
}).finally(()=>{
console.log('狗皮膏药');
})