前言
刚开始接触promise的时候,就很不理解promise到底是什么?怎么用?查找了大量资料,许多解释都是promise实例化,感觉还是不太明白,后来promise用的越来越多,也就有了自己的理解并总结思路写了这篇文章,如果想要学懂promise,带着这几个问题。
学习路线:
1:应用:
promise 是什么?
解决了什么问题?
特点是什么?
有哪些内容? 3个特殊属性
状态有几个? 3个
原型api有哪些?
静态api有哪些?
在什么时候使用?
2:promise A+
制定promise的规范。
3:基于原型或者class类如何手写promise。promise的原理是什么?
1:应用:什么是promise?
在此之前我们需要掌握一个知识点:同步和异步编程。
同步编程:在主线程上排队执行的任务,按从上至下执行代码,只有前一个执行完毕,才能执行后一个任务。
异步编程:不进入主线程,而进入“任务队列”的任务,只有“任务队列”通知主线程,某个异步任务可以执行了,这个任务才会进入主线程。
异步又分为:
1.微任务: promise.then回调 ,async
2. 宏任务:script,setTimeout ,setInterval的回调函数,ajax请求。
根据前面我们可以得出一个结论:存在异步任务的代码,不能保证能按顺序主席,那如果我们非要代码按顺序执行能?
// -------------------回调地狱------------------------
// 痛点:可维护,可读性问题. 不是性能,不是内存问题
//ajax请求
function ajax(options){
let {url='/',method='get',success} = options;
let xhr = new XMLHttpRequest();
// ...
xhr.onreadystatechange = ()=>{
if(xhr.readyState == 4 && xhr.status === 200){
success(xhr.responseText);
}
}
}
//连环请求
//痛点:太难看懂了.
ajax({
url:"/",
success:()=>{
ajax({
success:()=>{
ajax({
success(){
}
})
}
})
}
})
也许还会有更多的嵌套,像这种层层嵌套的回调函数就叫做回调地狱,而随之就有了promise。
Promise 是es6中新增加对象,产生是为了解决异步回调地狱问题,利用then函数的链式调用解决了异步回调地狱问题。
现在我们知道什么是promise,为什么用promise,那么掌握使用promise就是你的目标。
首先先了解promise有那些特点:
promise对象,指的是promise构造函数创建的实例对象。
promise的执行特点:
console.log(1);
let p = new Promise((resolve, reject) => {
// 1:该函数是不是回调函数? 是
// 2:该函数是同步执行还是异步执行? 同步执行
// 3:话说promise实例对象是为了解决异步回调地狱问题?
究竟哪里的程序是异步程序呢?then 的回调函数异步执行
console.log(2);
// 1 resolve 是触发 then实参一函数的条件之一
// 2 resolve 同步触发函数,但是 then的回调函数是异步触发的
// 因为then的回调函数,在Promise内部有多个执行条件,resolve执行只是条件之一
// bug: resolve赋值不是then的实参一,是Promise内部定义的函数
resolve()
// reject 是触发then 实参二函数的条件之一,也是触发catch的实参函数条件之一。
// reject()
})
console.log(3);
p.then(() => {
console.log(4); // 异步执行的
}, () => {
console.log('reject 触发');
})
console.log(5);
// 以上就是promise程序的特点,每行代码是什么,赋值的作用?
我们会好奇都是异步,为什么setTimeOut 回调执行,比 then 的回调慢?
then回调是微任务。setTimeOut是宏任务。在忽略Script情况下先微任务后宏任务。所以then会先输出。
promise有哪些状态,分别有什么作用
---> pending(开始) fulfilled(接受) rejected (拒绝)三种状态
描述过程:
---> pending
----> reoselve() ---> fulfilled
----> rejected() ---> rejected
promise中状态的变更,需要通过api 通知 prmise实例对象,状态应该变更了.
promise的实例对象有哪些内容呢?
let p = new Promise((resolve,reject)=>{
resolve(123) // 实参 给 [[PromiseResult]] 写值方式之一
// reject()
})
console.log(p);
我们查看输出的结果发现
* [[prototype]] 是p的原型对象 ----->有一些api
* [[PromiseState]] 作用:记录p的状态变化------> 无法读取修改,通过 api 修改状态
pending--->resolve()---> fulfilled
pending---> reject() --->rejected
* [[PromiseResult]] 作用:记录p的运算结果 ------->[[PromiseResult]] 读 写值特殊的
Promise常用方法
原型api:then 方法 、catch 方法、 finally 方法。
方法:resolve方法、reject 方法 、all方法、 race方法、any方法、allSettled方法。
1.then 方法接受两个参数:
let p = new Promise((resolve,reject)=>{
resolve(123)
})
let p1 = p.then((res)=>{
// 作用: fulfilled(已接受) 状态情况下,处理的业务
// 函数什么时候执行呢?
// res 是什么呢? p.[[PromiseResult]]的赋值
console.log(res);
// 问题:return 作用是什么? 是p.then() 的返回值
return '给p1.[[PromiseResult]]赋值'
},()=>{
console.log('reject');
})
console.log(p1);
作用:
1:实参一:处理状态变为 已接受
2:获取p中[[PromiseResult]]的赋值
3:实参二:处理 已拒绝状态的业务(不常用)
返回值:全新的promise实例对象, 状态已接受,结果:undefined
优势:支持then 链式调用
弊端: then 停不下来
2,catch 方法
相当于调用 then 方法, 但只传入 Rejected 状态的回调函数
let p1 = p.then(res=>{
console.log(1);
}).then(res=>{
console.log(2);
// 1:在then的链式调用用,只要有一个出现问题,后面的都不执行,执行catch
throw new Error('出错了出错了')
}).then(res=>{
console.log(3);
}).catch((err)=>{
// catch作用:1 捕获.then链式调用中的错误
// 2 处理 promis对象 的 已经拒绝的状态
console.log(4);
console.log(err);
})
// catch()
// 返回值是:pending状态的 全新的promise实例对象
catch 作用是什么
catch 回调函数作用是什么
catch 回调函数的形参赋值是什么
catch 返回值什么
catch 什么时候使用
可以用户统一处理 promise的已拒绝的状态
3.finally 方法
finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(123)
}, 1000)
})
let p1 = p.then(res=>{
console.log(1);
}).then(res=>{
console.log(3);
}).catch((err)=>{
console.log(4);
console.log(err);
}).finally(()=>{
// finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作
console.log('finally');
})
4.all
Promise.all()
作用:可以同时触发多个promise,用于处理并发任务, 等多个异步都结束的在执行下一个任务
let p = new Promise((resolve,reject)=>{
console.log('第一个异步任务开始了');
setTimeout(() => {
resolve('第一次异步结果')
}, 1000);
})
let p2 = new Promise((resolve,reject)=>{
console.log('第二个异步任务开始了');
setTimeout(() => {
resolve('第二次异步结果')
// reject()
}, 2000);
})
let p3 = new Promise((resolve,reject)=>{
console.log('第三个异步任务开始');
setTimeout(() => {
resolve('第三次异步结果')
}, 3000);
})
参数:元素:元素promise实例对象
返回值:全新的promise实例
[[PromiseResult]]:[p结果,p2结果,p3结果]
then 三个实例对象都变为 已接受状态 时候触发回调函数
回参:数组:数组元素为三个实例对象的[[promiseResult]],话句话三个实例对象的运算结果