6、promise

一、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方法的函数本体(函数定义)

修改状态值为fulfilled

二、利用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=>{
	
})

all方法

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('狗皮膏药');
})	
	

手写Promise原生代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值