promise
ES6语法规范中新增加的内置类,用来处理js中的异步编程的,而我们所谓的promise设计模式,就是基于promise对异步操作进行管理
异步编程中的“回调地狱”
-
Ajax的串行
-
只有第一个请求成功才能执行第二个,第二个成功才能执行第三个...最后一个请求成功后拿到了每一次请求的所有数据
$.ajax({
url:'/baseInfo',
method:'GET',
data:{
name:'zhanglu'
},
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=>{
}
});
}
});
}
});
-
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的三种状态
new Promise([executor]):第一个执行函数必须传递
[executor 简称EXE]
1.NEW PROMISE的时候就会把EXE执行,创建PROMISE的一个实例(EXE是PROMISE类的一个回调函数,PROMISE内部会把它执行)
2.PROMISE不仅把EXE执行,而且还给EXE传递两个参数(两个参数也是函数类型):
=>resolve函数:它执行代表PROMISE处理的异步事情是成功的,把PROMISE的状态改为fulfilled
=>reject函数:它执行代表PROMISE处理的异步事情是失败的,把PROMISE的状态改为rejected
.EXE函数中放的就是当前要处理的异步操作事情
![PROMISE的基础知识].png](cdn.nlark.com/yuque/0/201… "PROMISE的基础知识].png")
let promiseExamp = new Promise();
//=>UncaughtTypeError: Promise resolver undefined is not a function
//new Promise()需要传一个函数,传reolve(成功) reject(失败)的函数
let promiseExamp = new Promise((resolve, reject) => {
//=>这里一般存放的都是我们即将要处理的异步任务,任务成功我们执行resolve,任务失败我们执行reject
//(当然写同步的也可以)
let ran = Math.random();
setTimeout(() => {
if (ran < 0.5) {
reject(ran);
return;
}
resolve(ran);
}, 1000);
});
promiseExamp.then(result => {
//=>状态为FULFILLED成功后执行(RESULT:[[PromiseValue]])
console.log('成功: ' + result);
}, error => {
//=>状态为REJECTED失败后执行
console.log('失败: ' + error);
});
try catch解决代码报错,不影响后面代码继续执行
console.log(a); //=>Uncaught ReferenceError: a is not defined
let b = 10;
console.log(b); */
//=>在JS中当前行代码报错,会中断主线程的渲染(下面代码将不再行)
// throw new Error(''):手动抛出一个异常错误,目的就是让后代码不再执行
// 如果上面代码报错,不想让期影响后面的代码,我们需要做异常获:try catch finally
/* try {
console.log(a);
} catch (e) {
//=>错误信息
// console.log(e.message);
}
let b = 10;
console.log(b);
promise then设置成功或者失败后执行的方法
* Promise.prototype
* then:设置成功或者失败后执行的方法(成功或者失败都可以设置,也可以只设置一个)
* pro.then([success],[error])
* pro.then([success])
* pro.then(null,[error])
* catch:设置失败后执行的方法
* finally:设置不论成功还是失败都会执行的方法(一般不用)
/* let promiseExamp = new Promise((resolve, reject) => {
setTimeout(() => {
let ran = Math.random();
ran < 0.5 ? reject(ran) : resolve(ran);
}, 1000);
});
promiseExamp.then(result => {
console.log('成功: ' + result);
});
promiseExamp.catch(error => {
console.log('失败: ' + error);
});
promiseExamp.finally(x => {
console.log('哈哈');
});
promise的then的链式写法
执行then/catch/finally返回的结果是一个全新的promise实例,所以可以链式写下去,下一个then中哪一个方会被执行,由上一个then中的某个方法执行的结果来决定
1.这次执行哪一个方法,看上一个promise执行的状态是否出错和返回结果
2.上一个THEN中某个方法的返回值会传递给下一个THEN的某个方法中
new Promise((resolve, reject) => {
// resolve(100); //=>把第一个PROMISE实例的VALUE值改为100/-100
reject(-100);
}).then(result => {
console.log(result);
return result * 10; //=>THEN中RETURN的结果相当于把当前这个新的PROMISE实例中的VALUE值
改为返回值
}, err => {
console.log(err);
return err / 10;
}).then(A => {
console.log('A:' + A);
}, B => {
console.log('B:' + B);
}).then(C => {
}, D => {
});
如果当前PROMISE实例的状态确定后,都会到对应的THEN中找方法,如果THEN中没有对应的这个方法,则会向下顺延
THEN(onFulfilled) THEN(null,onRejected)
new Promise((resolve, reject) => {
reject(-100);
}).then(A => {
console.log(A);
return A * 10;
}).catch(B => {
console.log(B); //=>-100
return B * 10;
});
-------------------------------------------------------------------------------------
new Promise((resolve, reject) => {
resolve(100);
}).then(A => {
console.log(AAAAA); //=>执行报错,让.THEN创建的PROMISE实例变为失败状态,
并且把报错的原因修改此PROMISE的VALUE值
return A * 10;
}).catch(B => {
console.log(B); //=>ReferenceError: AAAAA is not defined
return '@';
}).then(C => {
console.log(C); //=>'@'
});
--------------------------------------------------------------------------------------
new Promise((resolve, reject) => {
resolve();
}).then().catch(x => {
console.log(1);
}).then(x => {
console.log(2); //=>OK
}).then(x => {
console.log(3); //=>OK
}).catch(x => {
console.log(4);
}).then(x => {
console.log('AAA'); //=>OK
console.log(AAA); //=>报错
}).catch().then(null, x => {
console.log(5); //=>OK
});
------------------------------------------------------------------------------------
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`)
});
let pro3 = pro2.then(result => {
console.log(`PRO1:SUCCESS`);
}, error => {
console.log(`PRO1:ERROR`)
});
解决Ajax回调地狱问题
function queryBase() {
return new Promise(resolve => {
$.ajax({
url: '/baseInfo?name=zhanglu',
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);
}
});
});
}
方法一:
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);
}); */
方法二:
/* queryBase().then(baseInfo => queryScore(baseInfo.scoreId))
.then(scoreInfo => queryChinese(scoreInfo.chinese))
.then(pai => {
console.log('排名是:' + pai);
}); */
方法三:
/* async function func() {
let baseInfo = await queryBase();
let scoreInfo = await queryScore(baseInfo.scoreId);
let pai = await queryChinese(scoreInfo.chinese);
//....
}
func();
解决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
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
Promise.race([ajax1(), ajax3(), ajax2()]).then(result => {
//=>看哪一个PROMISE状态最先处理完(成功或者失败),以最先处理完的为主
});