Promise设计模式
Promise是ES6中新增加的内置类:目的是为了管理异步操作的
1. new Promise() 创建一个类的实例,每一个是来都可以管理一个异步操作
-> 必须传递一个回调函数进去(回调函数中管理你的异步操作),不传递会报错
-> 回调函数中有两个参数
resolve:异步操作成功要做的事情(代指成功后 的事件队列=>成功后要做的所有事情都存放到这个事件队列中)
reject:异步操作失败哟啊做的事情(代指失败后的事件队列)
-> new Promise的时候立即把回调函数执行了(Promise是同步的)
let promise = new Promise(()=>{
$.ajax(...)
});
2. 基于Promise.prototype.then方法(还有catch / finally 两个方法)向成功队列和失败队列中依次加入需要处理的事情
-> 如果是多个then调用,不是像我们想象的依次把增加的方法执行,异步操作成功或者失败,先把第一个then中的方法执行,每执行一个then会返回一个新的Promise实例,这个实例管控的是第一个then中方法执行的成功还是失败
promise.then(result=>{ promise管控当前then中的成功或失败,执行完返回新的promise1
...
}).then(result=>{ promise1管控当前then中的成功或者失败,执行完返回新的promise2
...
}).then(result=>{ promise2...
...
});
->建议不要使用then中的第二个参数(这样看起来很乱),而是建议 我们使用Promise原型上的cache方法来管理我们的代码。
promise.then(result=>{ 异步请求成功则执行then中方法
...
}).catch(()=>{ 异步请求失败或第一个then方法执行失败,则执行catch
...
}).then(()=>{ 上一个then和catch执行成功,则执行then
}).catch(()=>{
}).finally(()=>{ //不管代码上一个promise成功还是失败都执行finally
});
3. 基于Promise解决回调地狱
//封装基于AJAX异步获取的数据
let queryA = function(){
return new Promise(()=>{
$.ajax({
url:'...',
success:result =>{
resolve(result);
}
});
});
};
let queryB = function(){
return new Promise(()=>{
$.ajax({
url:'...',
success:result =>{
resolve(result);
}
});
});
};
let queryC = function(){
return new Promise(()=>{
$.ajax({
url:'...',
success:result =>{
resolve(result);
}
});
});
};
//基于Promise管理异步获取的数据
let promise = queryA();
promise.then(result=>{
//操作queryA获取到的数据
//....
return queryB(); //在执行完queryB后获取到具体值后才能将这个具体值返回给下一个then
}).then(res=>{
//操作queryB获取到的数据
//....
return queryC();
}).then(res=>{
//操作queryC获取到的数据
//....
});
复习promise
new Promise((resolve,reject)=>{//在这个函数中可以管控异步操作
//resolve(); 成功
//reject(); 失败
}).then(result=>{ //每一次调取then方法,都会返回一个新的promise实例
//成功则执行resolve
}).catch(reason=>{ //相当与.then(null,reason=>{})
//失败执行
});
封装Promise库
原理
class Promise {
constructor(excutorCallBack) {
this.status = 'pending';
this.value = undefined;
this.fulfilledAry = [];
this.rejectedAry = [];
let resolveFn = result => {
let timer = setTimeout(() => {
clearTimeout(timer);
if (this.status !== 'pending') return;
this.status = 'fulfilled';
this.value = result;
this.fulfilledAry.forEach(item => {
item(this.value)
});
}, 0);
};
let rejectFn = reason => {
let timer = setTimeout(() => {
clearTimeout(timer);
if (this.status !== 'pending') return;
this.status = 'rejected';
this.value = reason;
this.rejectedAry.forEach(item => {
item(reason);
});
});
};
try {
excutorCallBack(resolveFn, rejectFn);
} catch (err) {
rejectFn(err);
}
}
then(fulfilledCallback, rejectedCallback) {
//处理不传参的情况
typeof fulfilledCallback !== 'function' ? fulfilledCallback = result => result : null;
typeof rejectedCallback !== 'function' ? rejectedCallback = reason => {
throw new Error(reason instanceof Error ? reason.message : reason);
} : null;
return new Promise((resolve, reject) => {
this.fulfilledAry.push(() => {
try {
let x = fulfilledCallback(this.value);
x instanceof Promise ? x.then(resolve, reject) : resolve(x);
} catch (err) {
reject(err);
}
});
this.rejectedAry.push(() => {
try {
let x = rejectedCallback(this.value);
x instanceof Promise ? x.then(resolve, reject) : resolve(x);
} catch (err) {
reject(err);
}
});
});
// this.fulfilledAry.push(fulfilledCallback);
// this.rejectedAry.push(rejectedCallback);
}
catch (rejectedCallback) {
return this.then(null, rejectedCallback);
}
static all(promiseAry = []) {
return new Promise((resolve, reject) => {
//index:记录成功的数量
//result:记录成功的结果
let index = 0,
result = [];
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then(val => {
index++;
result[i] = val; //索引和promiseAry对应上,保证结果的顺序和数组顺序一致
if (index === promiseAry.length) {
resolve(result);
}
}, reject);
}
});
}
}
module.exports = Promise;
//test1
let Promise = require('./promise_gmh');
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100);
}, 0);
}).then(result => {
// throw new Error('ERROR');
// console.log(result);
return result;
}).then(result => {}, reason => {
console.log(reason);
});
//test2
let Promise = require('./promise_gmh');
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100);
}, 50);
});
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(200);
}, 80);
});
let p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(300);
}, 10);
}).catch(itme => {
console.log(itme);
});
Promise.all([p1, p2, p3]).then(result => {
//=>所有的Promise都成功执行,result中分别存储每一个实例返回的结果,而且和数组中的顺序是一样的
console.log(result);
});//[100,200,300]