一、什么是promise?
ES6语法规范新增加的内置类,用来处理js中异步编程的,而我们所谓的promise设计模式,就事基于promise异步操作进行管理的
- console.dir(promise)
- new promise(function(){})
1.异步编程中的回调地狱
- 1.ajax的串行: 只有第一个请求成功才能执行第二个,第二个成功才能执行第三个,最后一个请求成功后,拿到了每一次请求的所有数据
//
$.ajax({
url:'/baseInfo',
method:'GET',
data:{
name:'zhangsan'
},
success:result=>{
let scoreId=result.scoreId;
$.ajax({
url:'/scoreInfo',
method:'GET',
data:{
id:scoreId
},
success:result=>{
let chinese=result.chinese;
$.ajax({
url:'/paiming',
method:'GET',
data:{
num:chinese
},
success:result=>{
}
})
}
})
}
})
- 2.ajax的并行:三个请求可以同时发送,但是需要等到所有请求都成功才会做一件事
let chi=100,
eng=12,
math=98;
let chiPai,
engPai,
mathPai;
let count=0;
function func(){
if(count>=3){
//处理要做的事情
}
}
$.ajax({
url:'/pai?chi='+chi,
success:result=>{
chiPai=result;
count++;
func();
}
});
$.ajax({
url:'/pai?eng='+eng,
success:result=>{
engPai=result;
count++;
func();
}
});
$.ajax({
url:'/pai?math='+math,
success:result=>{
mathPai=result;
count++;
func();
}
})
二、promise的executor函数和状态、
1.new Promise([executor]):第一个执行函数必须传递
- 1.new promise的时候就会吧executor执行,创建promise的一个实例(executor是promise类的一个回调函数,promise内部会吧它执行)
- 2.promise不仅把executor执行,而且还给executor传递两个参数(两个参数也是函数类型):
- resolve函数:它执行代表promise处理的异步事情是成功的,把promise的状态改为fulfilled
- reject函数:它执行代表promise处理的异步事情是失败的,把promise的状态改为reject
- 3.executor函数中放的就事当前要处理的异步操作事情
let promiseExE=new Promise();//=>Uncaught TypeError: Promise resolver undefined is not a function
let promiseExecutor=new Promise((resolve,reject)=>{
//这里 一般存放的都是我们即将要处理的异步任务,任务成功我们执行resolve,任务失败我们执行reject 当然写同步的也可以
setTimeout(()=>{
if(Math.random()<0.5){
reject();
return;
}
resolve();
},1000)
})
2.Promise的三个状态
- 1.pending:初始状态(new promise后的状态)
- 2.fulfilled:成功状态(在executor函数中把resolve执行,就事告知promise当前异步操作的结果是成功的)
- 3.rejected:失败状态(在executor函数中吧reject执行,就事告知promise当前异步操作的结果是失败的)
3.执行executor
- 1.执行executor函数,初始状态
let pro=new Promise([executor]);
[[PromiseStatus]]:'pending'
[[PromiseValue]]:undefined
-
2.把executor函数中异步操作开始执行:设置一个定时器,1000ms后执行定时器方法...等异步操作完成
-
3.在异步操作完成后,通过执行resolve/reject修改后pro的状态(假设当前案例执行的是resolve) let pro=new Promise([executor]); [[PromiseStatus]]:'fulfilled' [[PromiseValue]]:undefined
-
4.resolve和reject在执行的时候,我们可以给其传参,传递的参数值会修改pro的value值。 let pro=new Promise([executor]); [[PromiseStatus]]:'resolve' [[PromiseValue]]:'哈哈'
let promiseExeamp=new Promise((resolve,reject)=>{
setTimeout(()=>{
if(Math.random()<0.5){
reject('呵呵');
return;
}
resolve('哈哈');
},1000)
})
//=>控制台输出dir(promiseExeamp); 结果
// [[PromiseStatus]]:'resolve'
// [[PromiseValue]]:'哈哈'
三、promise中的then和catch
1.then(func1,func2)
let promiseExeamp=new Promise((resolve,reject)=>{
setTimeout(()=>{
let ran=Math.random();
if(ran<0.5){
reject(ran);
return;
}
resolve(ran);
},1000)
});
promiseExeamp.then(result=>{
//状态为fulfilled成功后执行(result:[PromiseValue])
console.log('成功:'+result);
},error=>{
//状态为rejected失败后执行
console.log('失败'+error)
})
2.then(func)
let promiseExeamp=new Promise((resolve,reject)=>{
setTimeout(()=>{
let ran=Math.random();
if(ran<0.5){
reject(ran);
return;
}
resolve(ran);
},1000)
});
promiseExeamp.then(result=>{
//状态为fulfilled成功后执行(result:[PromiseValue])
console.log('成功:'+result);
}
3.promise.prototype
- 1.then:设置成功或失败后执行的方法(成功或者失败都可以设置 也可以设置一个)
- pro.then([success],[error])
- pro.then([success])
- pri.then(null,[error])
- 2.catch:设置失败后执行的方法
- 3.finally:设置不论成功还是失败都会执行的方法(一般不用)
let promiseExeamp=new Promise((resolve,reject)=>{
setTimeout(()=>{
let ran=Math.random();
if(ran<0.5){
reject(ran);
return;
}
resolve(ran);
},1000)
});
promiseExeamp.then(result=>{
//状态为fulfilled成功后执行(result:[PromiseValue])
console.log('成功:'+result);
});
promiseExeamp.catch(error=>{
console.log('失败:'+error);
});
promiseExeamp.finally(x=>{
console.log('哈哈');
});
4.then链
- 1.then(onResolve,onReject)
- 2.执行then/catch/finally返回的结果是一个全新的promise实例
let pro1=new Promise((resolve,reject)=>{
setTimeout(()=>{
let ran=Math.random();
ran<0.5?reject(ran):resolve(ran);
},1000);
})
console.log(pro1);//=>Promise {<pending>}
let pro2=pro1.then(result=>{
},error=>{
});
console.log(pro2);//=>Promise {<pending>}
console.log(pro1===pro2);//=>false
let pro1=new Promise((resolve,reject)=>{
setTimeout(()=>{
let ran=Math.random();
ran<0.5?reject(ran):resolve(ran);
},1000);
})
console.log(pro1);//=>Promise {<pending>}
let pro2=pro1.then(result=>{
console.log(`PRO1:SUCCESS`);
},error=>{
console.log(`PRO1:ERROR`);//=>PRO1:ERROR
});
console.log(pro2);//=>Promise {<pending>}
- 2.执行then/catch/finally返回的结果是一个全新的promise实例,所以可以链式写下去,下一个THEN中那个方式会被执行,由上一个THEN中某个方法执行的结果来决定
let pro1=new Promise((resolve,reject)=>{
setTimeout(()=>{
let ran=Math.random();
ran<0.5?reject(ran):resolve(ran);
},1000);
});
let pro2=pro1.then(result=>{
console.log(`PRO1:SUCCESS`);
},error=>{
console.log(`PRO1:ERROR`);
});
console.log(pro2);//=>Promise {<pending>}
let pro3=pro2.then(result=>{
console.log(`PRO1:SUCCESS`);
},error=>{
console.log(`PRO1:ERROR`);
})
//随机的结果每次都不一样,所以执行结果也是根据每次随机结果而定
- 3.上一个THEN中某个方法的返回值会传递给下一个THEN的某个方法中
//1.失败
new Promise((resolve,reject)=>{
// resolve (100);
reject(-100);
}).then(result=>{
console.log(result);
},err=>{
console.log(err);//=>-100
})
//2.成功
new Promise((resolve,reject)=>{
resolve (100);
}).then(result=>{
console.log(result);//=>100
},err=>{
console.log(err);
})
//3.成功 两个then链
new Promise((resolve,reject)=>{
resolve (100);
}).then(result=>{
console.log(result);//=>100
},err=>{
console.log(err);
}).then(A=>{
console.log(A);//=>undefined
},B=>{
console.log(B);
})
//4.then链中带返回值
new Promise((resolve,reject)=>{
resolve (100);//=>把第一个promise实例value值改为100、-100
reject(-100);
}).then(result=>{
console.log(result);//=>100
//=>THEN中的return的结果相当于把当前这个新的promise实例中value值改为返回值
return result *10;
},err=>{
console.log(err);
return result/10;
}).then(A=>{
console.log('A:'+A);//=>1000
},B=>{
console.log('B:'+B);
});
//5.then链可以继续向下写
new Promise((resolve,reject)=>{
resolve (100);//=>把第一个promise实例value值改为100、-100
reject(-100);
}).then(result=>{
console.log(result);//=>100
//=>THEN中的return的结果相当于把当前这个新的promise实例中value值改为返回值
return result *10;
},err=>{
console.log(err);
return result/10;
}).then(A=>{
console.log('A:'+A);//=>1000
},B=>{
console.log('B:'+B);
}).then(C=>{
},D=>{
})
- 4.如果当前promise实例的状态确定后都会到对应的then中找到方法,如果then中没有对应的方法则会向下顺延
//1.失败
new Promise((resolve,reject)=>{
reject(-100);
}).then(A=>{
console.log('A:'+A);
return A*100;
}).catch(B=>{
console.log('B:'+B);//=>-100
return B*10;
});
//2.成功
new Promise((resolve,reject)=>{
resolve(100);
}).then(A=>{
console.log('A:'+A);//=>100
return A*100;
}).catch(B=>{
console.log('B:'+B);
return B*10;
});
//3. 提示报错
new Promise((resolve,reject)=>{
resolve(100);
}).then(A=>{
//=>执行报错,让then创建的promise实例变为失败状态,并且把报错的原因修改此promise的value值
console.log(AAAA);
return A*100;
}).catch(B=>{
console.log('B:'+B);//=>B:ReferenceError: AAAA is not defined
return '@';
});
//4.顺延练习题
new Promise((resolve,reject)=>{
resolve();
}).then(
//=>没有顺延
).catch(x=>{
console.log(1);
}).then(x=>{
console.log(2);//=>2
}).then(x=>{
console.log(3);//=>3
}).catch(x=>{
console.log(4);
}).then(x=>{
console.log(AAA);//=>AAA is not defined
console.log('AAA');//=>'AAA'
}).catch().then(null,x=>{
console.log(5);//=>5
});
四、promise其它常用方法
- 1.Promise.all
- 2.Promise.race
- 3.Promise.reject
- 4.Promise.resolve
1.解决AJAX回调地狱
function queryBase() {
return new Promise(resolve => {
$.ajax({
url: '/baseInfo?name=zhangsan',
success: result => {
resolve(result);
}
});
});
}
function queryScore(scoreId) {
return new Promise(resolve => {
$.ajax({
url: '/score?id=' + scoreId,
success: result => {
resolve(result);
}
});
});
}
function queryChinese(chinese) {
return new Promise(resolve => {
$.ajax({
url: '/paiming?chin=' + chinese,
success: result => {
resolve(result);
}
});
});
}
//1.写法一
queryBase().then(baseInfo => {
let scoreId = baseInfo.scoreId;
//=>THEN方法中如果返回的是一个PROMISE实例,则当前返回实例的成功或者失败状态,
//影响着下一个THEN中哪个方法会被触发执行;如果返回的是非PROMISE实例,
//则看当前方法执行是否报错,来决定下一个THEN中哪个方法执行;
return queryScore(scoreId);
}).then(scoreInfo => {
let chinese = scoreInfo.chinese;
return queryChinese(chinese);
}).then(pai => {
console.log('排名是:' + pai);
});
//2.写法二
queryBase().then(baseInfo => queryScore(baseInfo.scoreId))
.then(scoreInfo => queryChinese(scoreInfo.chinese))
.then(pai => {
console.log('排名是:' + pai);
});
//3.写法三
async function func() {
let baseInfo = await queryBase();
let scoreInfo = await queryScore(baseInfo.scoreId);
let pai = await queryChinese(scoreInfo.chinese);
//....
}
func();
2.解决AJAX并行
function ajax1() {
return new Promise(resolve => {
$.ajax({
url: '/api1',
success: resolve
});
});
}
function ajax2() {
return new Promise(resolve => {
$.ajax({
url: '/api2',
success: resolve
});
});
}
function ajax3() {
return new Promise(resolve => {
$.ajax({
url: '/api3',
success: resolve
});
});
}
// Promise.all([promise1,promise2,...]):ALL中存放的是多个PROMISE实例
//(每一个实例管理者一个异步操作),执行ALL方法返回的结果是一个新的PROMISE实例"PROA"
//=>当所有PROMISE实例的状态都为Fulfilled的时候(成功),让PROA的状态也变为Fulfilled,
//并且把所有PROMISE成功获取的结果,存储为成为一个数组(顺序和最开始编写的顺序一致)
//“result=[result1,result2,...]”,让PROA这个数组的VALUE值等于这个数组
//=>都成功(PROA状态是FUFILLED)才会通知THEN中第一个方法执行,只要有一个失败
//(PROA状态是REJECTED),就会通知THEN中第二个方法或者CATCH中的方法执行
Promise.all([ajax1(), ajax3(), ajax2()]).then(results => {
//=>results:[result1,result3,result2]
});
Promise.race([ajax1(), ajax3(), ajax2()]).then(result => {
//=>看哪一个PROMISE状态最先处理完(成功或者失败),以最先处理完的为主
});