Promise 简单来说是异步编程的一种解决方案
Promise对象有以下两个特点:
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。
(3)有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
promise的写法
let mypromise=new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(100)
},1000);
});
mypromise.then((res)=>{
console.log(res);
},()=>{
console.log("no");
})
复制代码
用promise写Ajax
let pro=new Promise((resolve,reject)=>{
let xhr=new XMLHttpRequest();
xhr.open("get","js/1.js",true);
xhr.onreadystatechange=()=>{
if(xhr.readyState===4 && xhr.status===200){
val=xhr.responseText;
resolve(val);
}
if(xhr.status!==200){
reject();
}
};
xhr.send();
});
pro.then((res)=>{
console.log(res);
获取数据//数据绑定
},()=>{
console.log("no不行");
})
复制代码
这样一来管理回调函数或者异步事件就很清楚了。可以后面继续追加.then();
then中两个方法,成功走第一个,失败走第二个,
比如实现某一种效果,就比如商品排序。
第一个then请求数据,绑定数据,渲染数据
第二个then从小到大排序
第三个then从大到小排序
let op=new Promise((resolve,reject)=>{
//Ajax请求数据
})
op.then((res)=>{
绑定数据//渲染数据
},()=>{
}).then(()=>{
//商品排序
})
...以此内推
复制代码
一旦在第一个then中return了,那么返回结果就给了第二个then,以此内推。
这种设计模式,功能很强大,也方便了许多,从上面可以看出 .then()可以写很多个,那么promise的实现原理是什么呢?
接下来就小手撸代码,进入正题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
class MyPromise{
constructor(excutor){
// 这里相当于MyPromise的函数体;
// 在promise中分三个状态;pending fulfilled rejected;
// this --> promise的实例;给实例新增state属性,其属性值是"pending";
this.state="pending";
// 在实例上找了两块空间;一个是用来存储成功的回调,一个用来存储失败的回调;
this.fulfilledEvent = [];
this.rejectedEvent = [];
this.value =undefined;
let resolve = (result)=>{
// resolve : 这个函数是用来管控所有成功态的函数执行;
// 一旦调用resolve,那么应该变成成功态;
//if(this.state==="fulfilled"||this.state==="rejected")return;
// 如果当前状态已经凝固,是成功或者失败中的一个,都不再执行;
if(this.state!=="pending")return;
this.state="fulfilled";
this.value=result;
clearTimeout(this.timer);
this.timer = setTimeout(()=>{
this.fulfilledEvent.forEach((item)=>{
if(typeof item==="function"){
item(this.value);
}
})
},0)
};
let reject=(result)=>{
if(this.state!=="pending")return;
this.state="rejected";
clearTimeout(this.timer);
this.value=result;
this.timer = setTimeout(()=>{
this.rejectedEvent.forEach((item)=>{
if(typeof item==="function"){
item(this.value);
}
})
},0)
}
try{
excutor(resolve,reject)
}catch(e){
// 如果在函数中抛出异常,那么会调用下面then的reject的方法;
reject(e);
}
}
then(resolveFn,rejectedFn){
if(resolveFn===undefined){
//如果then没有传递函数,那么给当前默认赋值一个函数
resolveFn=(result)=>{
return result
}
}
if(rejectedFn===undefined){
rejectedFn=()=>{
// 这个地方抛出异常,为了能够调用下个then的失败的方法;
throw new Error;
}
}
// 为了确保下一次的then方法中的回调受上一次then方法中返回值的影响,
//所以每次调用then,都返回一个不同的实例;
return new MyPromise((resolve,reject)=>{
// this --> then中this--> p1;
this.fulfilledEvent.push(()=>{
// 需要验证当前resolveFn函数的返回值是否是一个Promise的实例;
try{
let x = resolveFn();
x instanceof MyPromise?x.then(resolve,reject):resolve();
}catch(e){
reject(e)
}
});
this.rejectedEvent.push(()=>{
try{
let x = rejectedFn();
x instanceof MyPromise?x.then(resolve,reject):resolve();
}catch(e){
reject(e)
}
});
});
}
}
let p1 = new MyPromise(function (resolve,reject) {
resolve(200)
})
console.log(1);
let p2=p1.then(function (res) {
return new MyPromise(function (resolve,reject) {
reject();
})
},function () {
console.log(101);
});
p2.then(function () {
console.log(11);
},function () {
console.log(22);
})
</script>
</body>
</html>
复制代码
注意:
- 当new 一个promise时,promise中的函数会立马执行
- 当promise的状态一旦固定,就不再改变
- 无法取消Promise,一旦新建它就会立即执行,无法中途取消
- 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
- 当处于pending状态时,无法得知目前进展到哪一个状态
then方法
- then : 为promise的实例增加状态发生改变时的回调函数
- then: 把第一个then中的回调的返回值会传递给第二个then回调的函数的形参
- then : 方法中内置会返回一个新的promise的实例;但不是之前的那个promise的实例了
- 前面一个回调函数中如果返回一个promise的对象,那么第二个回调函数会等待第一个返回的promise实例的状态发生变化才执行
promise的catch
- catch : 捕获当前异步的错误信息
- 如果在catch之前已经有then将错误信息进行处理,那么不再执行这个catch方法
- 如果第一个请求失败,那么不会再执行第二个请求
- catch : 只要之前的请求有一个失败,都会触发这个catch方法
promise的all
- all : 是将多个Promise的实例包装成一个promise的实例
- all方法是Promise这个类的私有方法
- all方法传递一个数组,数组中存放着Promise的实例;all方法返回一个promise的实例
- p1的成功或者失败的状态由数组中每一个promise的实例决定;当所有的实例的状态都是成功态,那么该p1的状态才是成功态,只要有一个失败,那么这个就会执行失败态
let p1 = Promise.all([l1,l2,l3]).then(function () {},function () {})
复制代码