Promise设计模式
=>ES6提供的内置类,基于Promise可以有效的管理JS中的异步编程解决传统的异步编程+回调函数导致的“回调地狱”的问题,基于Promise进行异步管控的设计模式叫PROMISE设计模式
高阶函数(满足以下任意一个)
- ①一个函数的参数中有函数,那么当前这个函数就是高阶函数
- ②如果一个函数返回了一个函数,那么当前这个函数就是高阶函数
函数柯理化
- 目的: 利用闭包机制,把一些信息预先存储下来。细化函数功能,让他变得更具体一些
- 闭包: 函数执行会形成私有的上下文的机制就称为闭包
- 闭包的作用: 在这个上下文中有一些私有的变量AO,和外界的变量不会有冲突、
- 保存作用 在上下文中的返回值被外界占用,会形成不销毁的上下文,把所用到的信息存起来
- 缺点: 导致堆栈内存消耗过大,导致内存泄露,影响页面的运行效率,需要合理利用闭包
解析Promise运行机制
- let p = new Promise(executor)
- executor为一个函数
- 在创建实例的时候就把executor执行
- 并为exector传递俩个参数,都为函数 executor(RESOLVE,REJECT)
- executor(resolve,reject){管控异步代码}
- PROMISE实例p拥有俩个值:①PromiseStatus ②PromiseValue
- ①PromiseStatus 有三个状态:pending(准备状态)、fulfilled(操作成功完成)、resolved成功状态(在异步操作成功的时候,通过执行resolve函数,可以把当前的Promise实例状态变为成功态)、rejected失败状态(在异步操作失败的时候,通过执行reject函数,可以把当前的Promise实例状态变为失败态)
- ②PromiseValue: 是Promise实例的值,不论执行哪个函数,都可以将值传递给当前实例
- 通过RESOLVE、REJECT可以控制当前实例的状态和值。
- p.then([状态为成功时执行的函数],[状态为失败时执行的函数]),通过控制p的状态就是为了控制then中的哪个方法执行。
- 俩个函数参数接收的分别是p的PromiseValue
- then中的方法只会在实例状态为成功或者失败的时候才会执行
- Promise中的then链
- 用法:p.then().then()....
- 每一次执行then都会返回一个Promise实例
- 下一个then链返回的Promise实例状态由上一个then中的函数返回的结果决定
- 只要不报错,不论哪个方法执行,下一个then的Promise都为成功态,函数执行返回的值作为下一个then的Promise实例初始值,没有返回则为undefined
- 只要上一个then中报错,则下一个then实例状态为失败态
- 当上一个then中又返回一个新的Promise实例,即exector中有
new Promise()
,则会等待新的执行结果作为下一个then实例的初始状态 - then中不写RESOLVE,REJECT其中一个函数,Promise会补充一个函数
- 为了代码的可读性,规定catch()在失败的时候执行,then()在成功的时候执行,
catch(){ reason=>{...} } //代替 then(null,reason=>{...})
Promise作为普通对象=>静态私有属性方法
- Promise.all()
- Promise.race()
- Promise.resolve()
- Promise.reject()
Promise作为类-原型上共有的属性和方法
- Promise.prototype.then()
- Promise.prototype.catch()
- Promise.prototype.finally()
Promise语法糖
替代then链实现同步的异步等待效果。
-
async: async修饰符可以让一个普通的函数返回的结果变成一个Promise实例
-
await: await修饰符等待Promise成功,并获取到结果,再往下执行。
- async和await同时使用
- 只有await等待的实例的状态变为成功,才会把返回的结果赋值给变量,执行下边的代码
- await弊端:如果Promise实例状态为失败,下边的代码不再执行(
Uncaught(in Promise)
)


手写源码
/*
* Promise A+:Promise的设计规范
*/
class MyPromise {
constructor(executor) {
// 初始属性值
this.status = 'pending';
this.value = undefined;
this.resolvedArr = [];
this.rejectedArr = [];
// 改变状态的函数
let changeStatus = (status, result) => {
if (this.status !== 'pending') return;
this.status = status;
this.value = result;
let arr = status === 'rejected' ? this.rejectedArr : this.resolvedArr;
arr.forEach(item => (typeof item === 'function' ? item(this.value) : null));
};
let resolve = result => {
if (this.resolvedArr.length > 0) {
changeStatus('resolved', result);
return;
}
let delayTimer = setTimeout(() => {
clearTimeout(delayTimer);
changeStatus('resolved', result);
}, 0);
};
let reject = reason => {
if (this.rejectedArr.length > 0) {
changeStatus('rejected', reason);
return;
}
let delayTimer = setTimeout(() => {
clearTimeout(delayTimer);
changeStatus('rejected', reason);
}, 0);
};
// 异常捕获处理
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(resolvedFn, rejectedFn) {
if (typeof resolvedFn !== 'function') {
resolvedFn = result => {
return result;
};
}
if (typeof rejectedFn !== 'function') {
rejectedFn = reason => {
// throw new Error(reason);
return new MyPromise((resolve, reject) => {
reject(reason);
});
};
}
// then链:返回一个新的Promise实例
return new MyPromise((resolve, reject) => {
this.resolvedArr.push(() => {
try {
let x = resolvedFn(this.value);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
} catch (error) {
reject(error);
}
});
this.rejectedArr.push(() => {
try {
let x = rejectedFn(this.value);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
} catch (error) {
reject(error);
}
});
});
}
catch (rejectedFn) {
// catch(rejectedFn) === then(null,rejectedFn)
return this.then(null, rejectedFn);
}
/* 静态方法 */
static resolve(result) {
return new MyPromise(resolve => {
resolve(result);
});
}
static reject(reason) {
return new MyPromise((_, reject) => {
reject(reason);
});
}
static all(arr) {
return new MyPromise((resolve, reject) => {
let index = 0,
results = [];
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (!(item instanceof MyPromise)) continue;
item.then(result => {
index++;
results[i] = result;
if (index === arr.length) {
resolve(results);
}
}).catch(reason => {
// 只要有一个失败,整体就是失败
reject(reason);
});
}
});
}
}
module.exports = MyPromise;