Promise规范及应用
PromiseA+规范相关术语:
-
promise是一个有then方法的对象或函数,行为遵循本规范
-
thenable是一个有then方法的对象或函数
-
value是promise状态成功时的值,也就是resolve的参数,包括各种参数,也包括undefined/thenable或是promise
-
reason是promise状态失败时的值,也就是reject参数,表示拒绝的原因
-
exception是一个使用throw抛出的异常值
PromiseA+规范
Promise States
Promise三种状态及他们之间的流转关系。
- pending
1.1 初始的状态,可变化
1.2 promise实例在resolve或reject前处于这个状态
1.3 可以通过resolve转化成fulfilled状态
1.4 可以通过reject转化为rejected状态
- fulfilled
2.1 最终态,不可变
2.2 一个promsie被resolve后会变成这个状态
2.3 必须拥有一个value值
- rejected
3.1 最终态,不可变
3.2 一个promise被reject后变成的状态
3.3 必须拥有一个reason
then
Promise应该提供一个then方法,用来访问最终的结果,无论是value还是reason
promise.then(onFulfilled, onRejected)
- 参数要求
onFulfilled,onRejected必须是函数
- onFulfilled特性
在promise变成fulfilled时调用,参数是value。只能调用一次(代码中需要体现)
- onRejected特性
在promise变成rejected时调用,只能被调用一次(代码体现)
- onFulfilled和onRejectes应该该是微任务
这里用queueMicrotask来实现微任务调用
- then方法可以被调用多次
5.1 promise状态变成filfilled后,所有onFulfilled回调都需要按照then的顺序执行,也就是按照注册顺序执行(实现时需要一个数组来存放多个onFulfilled的回调)
5.2 promise状态变成rejected后,所有的onRejected回调需要按照注册顺序执行(所以在实现的时候需要一个数组来存放多个onRejected的回调)
- 返回值
then 应该返回一个promise
promise2 = promise1.then(onFulfilled, onRejected);
6.1 onFulfilled 或 onRejected 执行的结果为x,调用resolvePromise
6.2 如果 onFulfilled 或者 onRejected 执行时抛出异常e,promise2需要被reject
6.3 如果onFulfilled不是一个函数,promise2以promise1的value触发fulfilled
6.4 如果 onRejected 不是一个函数,promise2以promise1的reason触发rejected
- resolvePromise
resolvePromise(promise2, x, resolve, reject)
7.1 如果 promise2 和 x 相等,那么 reject TypeError
7.2 如果 x 是一个 promise
如果x是pending态,那么promise必须要在pending,直到x变成filfilled or rejected.
如果x被fulfilled,fulfill promise with the same value.
如果x被rejected,reject promise with the same reason.
7.3 如果x是一个object或是一个function
let then = x.then.
如果x.then这步出错,那么reject promise with e as the reason.
如果then是一个函数,then.call(x, resolvePromiseFn, rejectPromise)
resolvePromiseFn的入参是y,执行resolvePromise(promise2, y, resolve, reject);
rejectPromise的入参是r,reject promise with r.
如果resolvePromise和rejectPromise都调用了,那么第一个调用优先
如果调用then抛出异常e
如果resolvePromise或rejectPromise已经被调用,则忽略
则,reject promise with e as the reason
如果then不是一个function。fulfill promise with x.
promise代码实现
- new Promise()
class MPromise {
constructor(){}
}
- 定义三种状态类型
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
- 设置初始状态
class MPromise{
constructor() {
this.status = PENDING;
this.value = null;
this.reason = null;
}
}
-
resolve 和 reject方法
-
根据刚才的规范,这两个方法是要更改status的,从pending改到fulfilled/rejected.
-
两个函数的入参分别是value和reason
class MPromise{
constructor() {
// 初始状态为pending
this.status = PENDING;
this.value = null;
this.reason = null;
}
resolve(value) {
if(this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
}
}
reject(reason) {
if(this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
}
}
}
-
promise入参
-
入参是一个函数,函数接受resolve和reject两个参数
-
初始化promise的时候,就需要执行resolve或reject,报错需要reject抛出
class MPromise {
this.status = PENDING;
this.value = null;
this.reason = null;
try {
fn(this.resolve.bind(this), this.reject.bind(this))
} catch(e) {
this.reject(e)
}
resolve(value) {
if(this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
}
}
reject(reason) {
if(this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
}
}
}
-
then方法
-
then就收两个参数,onFulfilled和onRejected
then(onFulfilled, onRejected){}
- 检查并处理参数,如果不是function,直接鸳鸯返回value或reason
isFunction(param) {
return typeof param === 'function'
}
then(onFulfilled, onRejected) {
const realOnFulfilled =this.isFunction(onFulfilled) ? onFulfilled : (value) => {
return value;
}
const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => {
throw reason
}
}
- 要知道.then的返回值整体上是一个promise,所以咱们先用promise来包裹一下,
then(onFulfilled, onRejected) {
const realOnfulfilled = this.isFunction(onFulfilled) ?
onFulfilled : (value) => {
return value
}
const realOnRejected = this.isFunction(onRejected) ?
onRejected : (reason) => {
throw reason
};
const promise2 = new MPromise((resolve, reject) =>{})
return promise2;
}
- 根据当前promise状态,调用不同的函数
then(onFulfilled, onRejected) {
const realOnfulfilled = this.isFunction(onFulfilled) ?
onFulfilled : (value) => {
return value
}
const realOnRejected = this.isFunction(onRejected) ?
onRejected : (reason) => {
throw reason
};
const promise2 = new MPromise((resolve, reject) =>{
switch(this.status) {
case FULFILLED: {
realOnFulfilled();
break;
}
case REJECTED: {
realOnRejected();
break;
}
}
})
return promise2;
}
-
pending状态监听,但状态变成fulfilled或rejected再去执行callback.
-
储存成功和失败的回调,调用then的时候,如果还是pending就存入数组,
FULFILLED_CALLBACK_LIST = [];
REJECTED_CALLBACK_LIST = [];
then(onFulfilled, onRejected) {
const realOnfulfilled = this.isFunction(onFulfilled) ?
onFulfilled : (value) => {
return value
}
const realOnRejected = this.isFunction(onRejected) ?
onRejected : (reason) => {
throw reason
};
const promise2 = new MPromise((resolve, reject) =>{
switch(this.status) {
case FULFILLED: {
realOnFulfilled();
break;
}
case REJECTED: {
realOnRejected();
break;
}
case PENDING: {
this.FULFILLED_CALLBACK_LIST.push(realOnFulfilled)
this.REJECTED_CALLBACK_LIST.push(realOnRejected)
}
}
})
return promise2;
}
- 在status发生变化的时候,就执行所有的回调。可以利用es6的getter和setter(也可以在status赋值后顺序执行)
_status = PENDING;
get status() {
return this._status;
}
set status(newStatus) {
this._status = newStatus;
switch(newStatus) {
case FULFILLED: {
this.FULFILLED_CALLBACK_LIST.forEach((callback) =>{
callback(this.value);
});
break;
}
case REJECTED: {
this.REJECTED_CALLBACK_LIST.forEach((callback) =>{
callback(this.reason)
});
break;
}
}
}
-
Then的返回值是一个promise,改promise的value和reason是什么
-
如果onFulfilled或onRejected抛出一个异常e,则promise2必须拒绝执行,并返回决绝的原因e(手动catch代码,遇到报错就reject)
then(onFulfilled, onRejected) {
const realOnfulfilled = this.isFunction(onFulfilled) ? onFullfilled : (value) => {
return value;
}
const realOnRejected = this.isFunction(onRejected) ?
onRejected : (reason) => {
throw reason
}
const promise2 = new MPromise((resolve, reject) => {
const fulfilledMicrotask = () => {
try {
realOnFulfilled(this.value);
} catch(e) {
reject(e)
}
};
const rejectedMicrotask = () => {
try {
realOnRejected(this.reason);
} catch(e) {
rehect(e)
}
}
switch(this.status) {
case FULFILLED: {
fulfilledMicrotask();
break;
}
case REJECTED: {
rejectedMicrotask();
break;
}
case PENDING: {
this.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask)
this.REJECTED_CALLBACK_LIST.push(rejectedMicrotask)
}
})
return promise2;
}
-
如果onFulfilled不是函数且promise1成功执行,promise2必须成功执行并返回相同的值
-
如果onRejected不是函数且promise1拒绝执行,promise2必须拒绝执行并返回相同的据因
如果promise1的onRejected执行成功了,promise2应该被resolve???
- 如果onFulfilled或onRejected返回一个值x,则运行resolvePromise方法
then(onFulfilled, onRejected) {
const realOnfulfilled = this.isFunction(onFulfilled) ? onFullfilled : (value) => {
return value;
}
const realOnRejected = this.isFunction(onRejected) ?
onRejected : (reason) => {
throw reason
}
const promise2 = new MPromise((resolve, reject) => {
const fulfilledMicrotask = () => {
try {
const x = realOnFulfilled(this.value);
this.resolvePromise(promise2,x,resolve,reject);
} catch(e) {
reject(e)
}
};
const rejectedMicrotask = () => {
try {
const x = realOnRejected(this.reason);
this.resolvePromise(promise2,x,resolve,reject)
} catch(e) {
rehect(e)
}
}
switch(this.status) {
case FULFILLED: {
fulfilledMicrotask();
break;
}
case REJECTED: {
rejectedMicrotask();
break;
}
case PENDING: {
this.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask)
this.REJECTED_CALLBACK_LIST.push(rejectedMicrotask)
}
})
return promise2;
}
- resolvePromise
resolvePromise(promise2,x, resolve, reject) {
// 如果 newPromise 和 x 指向同一个对象,以TypeError为据因拒绝执行 newPromise
// 防止死循环
if(promise2 === x) {
return reject(new TypeError(''))
}
if(x instanceof MPromise) {
// 如果x为Promise,则使newPromise接受x的状态
// 也就是继续执行x,如果执行的时候拿到一个y,还要继续解析y
queueMicrotask(()=>{
x.then((y)=>{
this.resolvePromise(promise2, y, resolve, reject);
}, reject);
})
} else if(typeof x === 'object' || this.isFunction(x)) {
// 如果x为对象或者函数
if(x=== null) {
// null也会被判断为对象
return resolve(x);
}
let then = null;
try {
// 把 x.then复制给then
then = x.then;
} cantch(error) {
// 如果取x.then的值时抛出错误e,则以e为据因拒绝promise
return reject(error);
}
// 如果then是函数
if(this.isFunction(then)) {
let called = false;
// 将x作为函数的作用域this调用
// 传递两个回调函数作为参数,第一个参数叫做 resolvePromise,第二个参数叫做 rejectPromise
try {
then.call(x,
// 如果 resolvePromise 以值y作为参数被调用,则运行resolvePromise
(y) => {
// 需要有一个变量called来保证只调用一次
if(called) return;
called = true;
this.resolvePromise(promise2, y, resolve, reject);
},
// 如果rejectPromise以据因r为参数被调用,则以据因r拒绝promise
(r) => {
if(called) return;
called = true;
reject(r)
}
)
} catch(error) {
// 如果调用 then 方法抛出异常e
if(called) return;
// 否则以e为据因拒绝promise
reject(error);
}
} else {
// 如果 then 不是函数,以 x 为参数执行 promise
resolve(x);
}
} else {
// 如果 x 部位对象或函数,以 x 为参数执行 promise
resolve(x);
}
}
- onFulfilled 和 onRejected 是微任务
我们可以用queueMicrotask包裹执行函数
const fulfilledMicrotask = () => {
queueMicrotask(() => {
try {
const x = realOnfilled(this.value);
this.resolvePromise(promise2, x, resolve, reject);
} catch(e) {
reject(e)
}
})
}
const rejectedMicrotask = () => {
queueMicrotask(() => {
try {
const x = realOnRejected(this.reason);
this.resolvePromise(promise2,x, resolve, reject);
} catch(e) {
reject(e)
}
})
}
- catch方法
catch(onRejected) {
return this.then(null, onRejected);
}
- promise.resolve
将现有对象转换为Promise对象,如果 Promise.resolve 方法的参数,不是具有 then 方法的对象(thenable 对象),则返回一个新的 Peomise 对象,且他的状态为fulfilled.
是静态方法
static resolve(value) {
if(value instanceof MPromise) {
return value;
}
return new MPromise((resolve) => {
resolve(value)
})
}
- promise.reject
返回一个新的Promise实例,该实例的状态为rejected.
Promise.reject方法的参数reason,会被传递给实例的回调函数。
static reject(reason) {
return new MPromise((resolve, reject) => {
reject(reason)
})
}
- promise.race
const p = Promise.race([p1, p2, p3]);
该方法是将多个Promise实例,包装成一个新的Promise实例。
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着变化。那个率先改变的
Promise 实例的返回值,就传递给p的回调函数。
static race(promiseList) {
return new MPromise((resolve, reject) => {
const length = promiseList.length;
if(length === 0) {
return resolve();
} else {
for (let i=0; i<length; i++) {
MPromise.resolve(promiseList[i]).then((value) => {
return resolve(value);
}),
(reason) => {
return reject(reason);
}
}
}
})
}
\
Generator 和 Async 简介
迭代器 Iterator
迭代器Iterator是ES6引入的一种新的遍历机制,同时也是一种特殊对象,它具有一些专门为迭代过程设计的专有接口。
每个迭代对象都有一个next()方法,每次调用都返回一个当前对象。当前对象中有两个属性:
-
value: 当前属性值
-
done: 用于判断是否遍历结束,当没有更多返回的数据时,返回true
没调用一次next()方法,都会返回一个可用的值,直到遍历结束。
生成器 Generator
生成器是一种返回迭代器的函数,通过function关键字后的星号(*)来表示,函数中会用到新的关键字 yield。星号可以紧挨着function关键字,也可以在中间添加一个空格。
function* generator() {
const list = [1,2,3];
for (let i of list) {
yield i;
}
}
let g = generator();
console.log(g.next()); // {value: 1, done: false}
console.log(g.next()); // {value: 2, done: false}
console.log(g.next()); // {value: 3, done: false}
console.log(g.next()); // {value: undefined, done: true}
-
每当执行完一条yield语句后函数就会自动停止执行,直到再次调用next();
-
yield关键字只能在生成器内部使用,不然会报错
-
可以通过函数表达式来创建生成器,但不能使用箭头函数
let generator = function* (){}
async 和 await
如何让generator自动执行完毕?
function longTimeFn(time) {
return new Promise(resolve => {
setTimeout(() => {
resolve(time);
}, time)
})
}
function asyncFunx(generator) {
const iterator = generator(); // 接下来要执行next
// data为第一次执行之后的返回结果,用于传给第二次执行
const next = (data) => {
const {value, done} = iterator.next(data); // 第二次执行,并接收第一次的请求结果 value 和 done
if (done) return; //执行完毕,直接返回
// 第一次执行next时,yield返回的promise实例 赋值给了 value
value.then(data => {
next(data); // 当第一次value执行完毕且成功时,执行下一步(并把第一次的结果传递到下一步)
})
}
next();
}
\