实现promise

92 阅读9分钟

Promise规范及应用

PromiseA+规范相关术语:

  1. promise是一个有then方法的对象或函数,行为遵循本规范

  2. thenable是一个有then方法的对象或函数

  3. value是promise状态成功时的值,也就是resolve的参数,包括各种参数,也包括undefined/thenable或是promise

  4. reason是promise状态失败时的值,也就是reject参数,表示拒绝的原因

  5. exception是一个使用throw抛出的异常值

PromiseA+规范

Promise States

Promise三种状态及他们之间的流转关系。

  1. pending

1.1 初始的状态,可变化

1.2 promise实例在resolve或reject前处于这个状态

1.3 可以通过resolve转化成fulfilled状态

1.4 可以通过reject转化为rejected状态

  1. fulfilled

2.1 最终态,不可变

2.2 一个promsie被resolve后会变成这个状态

2.3 必须拥有一个value值

  1. rejected

3.1 最终态,不可变

3.2 一个promise被reject后变成的状态

3.3 必须拥有一个reason

then

Promise应该提供一个then方法,用来访问最终的结果,无论是value还是reason

promise.then(onFulfilled, onRejected)

  1. 参数要求

onFulfilled,onRejected必须是函数

  1. onFulfilled特性

在promise变成fulfilled时调用,参数是value。只能调用一次(代码中需要体现)

  1. onRejected特性

在promise变成rejected时调用,只能被调用一次(代码体现)

  1. onFulfilled和onRejectes应该该是微任务

这里用queueMicrotask来实现微任务调用

  1. then方法可以被调用多次

5.1 promise状态变成filfilled后,所有onFulfilled回调都需要按照then的顺序执行,也就是按照注册顺序执行(实现时需要一个数组来存放多个onFulfilled的回调)

5.2 promise状态变成rejected后,所有的onRejected回调需要按照注册顺序执行(所以在实现的时候需要一个数组来存放多个onRejected的回调)

  1. 返回值

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

  1. 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代码实现

  1. new Promise()

class MPromise {

constructor(){}

}

  1. 定义三种状态类型

const PENDING = 'pending';

const FULFILLED = 'fulfilled';

const REJECTED = 'rejected';

  1. 设置初始状态

class MPromise{

constructor() {

this.status = PENDING;

this.value = null;

this.reason = null;

}

}

  1. resolve 和 reject方法

  2. 根据刚才的规范,这两个方法是要更改status的,从pending改到fulfilled/rejected.

  3. 两个函数的入参分别是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;

}

}

}

  1. promise入参

  2. 入参是一个函数,函数接受resolve和reject两个参数

  3. 初始化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;

}

}

}

  1. then方法

  2. then就收两个参数,onFulfilled和onRejected

then(onFulfilled, onRejected){}

  1. 检查并处理参数,如果不是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

}

}

  1. 要知道.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;

}

  1. 根据当前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;

}

  1. pending状态监听,但状态变成fulfilled或rejected再去执行callback.

  2. 储存成功和失败的回调,调用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;

}

  1. 在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;

}

}

}

  1. Then的返回值是一个promise,改promise的value和reason是什么

  2. 如果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;

}

  1. 如果onFulfilled不是函数且promise1成功执行,promise2必须成功执行并返回相同的值

  2. 如果onRejected不是函数且promise1拒绝执行,promise2必须拒绝执行并返回相同的据因

如果promise1的onRejected执行成功了,promise2应该被resolve???

  1. 如果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;

}

  1. 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);

}

}

  1. 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)

}

})

}

  1. catch方法

catch(onRejected) {

return this.then(null, onRejected);

}

  1. promise.resolve

将现有对象转换为Promise对象,如果 Promise.resolve 方法的参数,不是具有 then 方法的对象(thenable 对象),则返回一个新的 Peomise 对象,且他的状态为fulfilled.

是静态方法

static resolve(value) {

if(value instanceof MPromise) {

return value;

}

return new MPromise((resolve) => {

resolve(value)

})

}

  1. promise.reject

返回一个新的Promise实例,该实例的状态为rejected.

Promise.reject方法的参数reason,会被传递给实例的回调函数。

static reject(reason) {

return new MPromise((resolve, reject) => {

reject(reason)

})

}

  1. 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()方法,每次调用都返回一个当前对象。当前对象中有两个属性:

  1. value: 当前属性值

  2. 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}

  1. 每当执行完一条yield语句后函数就会自动停止执行,直到再次调用next();

  2. yield关键字只能在生成器内部使用,不然会报错

  3. 可以通过函数表达式来创建生成器,但不能使用箭头函数

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();

}










\