1.术语
- 1.
promise
是一个有then方法的对象或者函数 - 2.
thenable
是一个有then方法的对象或者函数 - 3.
value
是promise成功态的值,值的类型是任何符合JS规范的类型 - 4.
exception
是throw抛出异常的值 - 5.
reason
是promise失败态的值
2.Promise A+规范
2.1.Promise States
一个promise必须处于三种状态中之一:
- 1.pending「等待态」
- 2.fulfilled「成功态」∏
- 3.rejected「失败态」
2.1.1.pending
- 初始化的状态,可以改变
- 可以转化为成功态,或者失败态
2.1.2.fulfilled
- 最终态,不可变
- pending->resolve(value)->fulfilled
- 必须拥有一个value值
2.1.3.rejected
- 最终态,不可变
- pending->reject(reason)->rejected
- 必须拥有一个reason值
2.1.4.改变状态
pending->resolve->fulfilled 「最终态,一旦成功不能在失败」 pending->reject->rejected 「最终态,一旦失败不能在成功」 pending->throw new Error('')->rejected
2.2.then方法
Promise必须提供一个then方法,用来访问最终的结果,无论是value还是reason
promise.then(onFulfilled,onRejected);
2.2.1.参数要求
- 如果
onFulfilled
不是函数,必须忽略它 「值的穿透」 - 如果
onRejected
不是函数,必须忽略它 「值的穿透」
2.2.2.onFulfilled
- 当状态变为fulfilled时,应该调用onFulfilled,参数为value
- 在状态是fulfilled之前,onFulfilled不被调用
- onFulfilled不能被多次调用
2.2.3.onRejected
- 当状态为rejected时,应该嗲用onRejected,参数为reason
- 在状态是rejected之前,onRejected不被调用
- onRejected不能被多次调用
2.2.4.onFulfilled和onRejected要异步执行
可以通过宏任务或者微任务实现
- 宏任务:setTimeout或setImmediate
- 微任务:MutationObserver或者process.nextTick
2.2.5.then方法可以被调用多次
- promise状态变为fulfilled后,所有的onFulfilled回调都需要按照then的顺序执行,也就是按照注册顺序执行
- promise状态变为rejected后,所有的onRejected回调都需要按照then的顺序执行,也就是按照注册的顺序执行
2.2.6.then的返回值
then的返回值应该是一个新的promise
promise2 = promise1.then(onFulfilled, onRejected);
- onFulfilled或onRejected执行后的结果是x,调用resolvePromise(promise2,x,resolve,reject)
- 如果 onFulfilled或者 onRejected执行抛出异常,promise2需要reject这个异常
- 如果onFulfilled不是一个函数,promise2以promise1的value触发fulfilled
- 如果onRejected不是一个函数,promise2以promise1的reason触发这个rejected
2.2.7.resolvePromise
resolvePromise(promise2,x,resolve,reject);
-
如果promise2和x相同,需要reject一个类型异常「TypeError 不然会死循环」
-
如果x是一个promise
- 如果处于pending态中的x,promise必须继续等待,直到x变为fulfilled/rejected
- 如果处于fulfilled态中的x,promise则以相同的值完成
- 如果处于rejected态中的x,promise以同样的理由拒绝
-
如果x是一个object或着function
-
let then=x.then
-
- 如果x.then出错,那么promise以同样的理由拒绝
-
- 如果then是一个函数,then.call(x,resolvePromiseFn,rejectPromiseFn)
- resolvePromiseFn的入参是y,执行resolvePromise(promise2,y,resolve,reject)
- rejectPromiseFn的入参是r,执行reject(r);
- 如果resolvePromiseFn和rejectPromiseFn都被调用了,那么第一个调用优先,后面的调用忽略
-
- 如果then执行抛出异常
- 如果resolvePromiseFn或者rejectPromiseFn已经被调用,那么忽略
- reject抛出的异常
-
-
如果then是一个普通值,直接resolve(x);
3.实现
3.1.定义三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
3.2.class实现一个Promise
- 1.new Promise是传递一个构造器「executor」
- 2.executor默认就要执行,并且参数为resolve,和reject函数
- 3.resolve函数,用来处理从等待态到成功态,并且给value赋值
- 4.reject函数,用来处理从等待态到失败态,并且给reason赋值
- 5.executor执行时,可能出错,出错需要reject异常
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class Promise {
constructor(executor) {
//初始化状态
this.state = PENDING;
//成功是的值
this.value = null;
//失败时的值
this.reason = null;
const resolve = (value) => {
if (this.state === PENDING) { //pending->resolve->fulfilled
this.state = FULFILLED;
this.value = value;
}
}
//pending->reject(reason)->rejected
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
}
}
try { //pending->throw new Error->rejected
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
}
3.3.then方法
3.3.1.onFulfilled,onRejected
- 接受两个参数,onFulfilled,onRejected
- onFulfilled的不是一个函数时,值要往下传递「值的穿透」
- onRejected的不是一个函数是,值要往下传递「值的穿透」
then(onFulfilled,onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : e => {
throw e
}
}
3.3.2.then的返回值是一个新的promsie
如果then的返回值不是一个新的promise会存在一个问题,就是违背一旦成功或者失败是已经是最终态了,接下来的then没办法处理
then(onFulfilled,onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : e => {
throw e
}
const promise2=new Promise((resolve,reject)=>{})
return promise2;
}
3.3.3.处理不同的状态
- FULFILLED:立即成功时的处理
- REJECTED:立即失败时的处理
then(onFulfilled,onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : e => {
throw e
}
const promise2=new Promise((resolve,reject)=>{
switch (this.state) {
case FULFILLED:
onFulfilled(this.value);
break;
case REJECTED:
onRejected(this.reason);
break;
}
})
return promise2;
}
3.3.4.等待态的处理
上面的逻辑我们已经看到,then函数被调用的瞬间就会执行,但是这样对应一个异步来说,它的状态不会立马变成fulfilled或者rejected,该怎么办呢?这时候状态实质时处于等待态的,所有这个时候我们需要一个状态的监听机制,当状态变为fulfilled或者rejected后,再去执行callback,这个我们采用发布订阅模式
- 1.创建一个_fulfilled_callback_list用来存放成功的回调
- 2.创建一个_rejected_callback_list用来存放失败的回调
- 3.当pending->resolve->fulfilled时,循环执行订阅的
- 4.当pending->reject->rejected时,循环执行订阅的
const promise2=new Promise((resolve,reject)=>{
switch (this.state) {
case FULFILLED:
onFulfilled(this.value);
break;
case REJECTED:
onRejected(this.reason);
break;
case PENDING:
this._fulfilled_callback_list.push(
() => {
onFulfilled(this.value);
})
this._rejected_callback_list.push(
() => {
ronRejected(this.reason);
})
}
})
//存储所以等待态中的fulfilled回调
this._fulfilled_callback_list = [];
//存放所用等待态的onRejected
this._rejected_callback_list = [];
const resolve = (value) => {
//may transition to either the fulfilled or
rejected state.
if (this.state === PENDING) { //
pending->resolve->fulfilled
this.value = value;
this.state = FULFILLED;
this._fulfilled_callback_list.forEach
(cb => cb());
}
}
//pending->reject(reason)->rejected
const reject = (reason) => {
//may transition to either the fulfilled or
rejected state.
if (this.state === PENDING) {
this.reason = reason;
this.state = REJECTED;
this._rejected_callback_list.forEach(cb
=> cb());
}
}
3.3.5.promise2
- 1.onFulfilled,onRejected执行可能抛错,promise2必须拒绝执行
- 2.onFulfilled,onRejected执行的返回值,可能任意类型「promise...」,需要resolvePromise这个值,处理不同情况
- 3.resolvePromise(promise2,x,resolve,reject)中的promise2可能不存在,需要异步处理「这里采用setTimeout实现」
//A promise must provide a then method to access its current or eventual value or reason
then(onFulfilled, onRejected) {
//If onFulfilled is not a function, it must be ignored.
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
//If onRejected is not a function, it must be ignored.
onRejected = typeof onRejected === 'function' ? onRejected : e => {
throw e
}
const promise2 = new Promise((resolve, reject) => {
let realOnFulfilled = () => {
setTimeout(() => { //onFulfilled or onRejected must not be called until the execution
context stack contains only platform code
try {
//If either onFulfilled or onRejected returns a value x, run the Promise
Resolution Procedure [[Resolve]](promise2, x)
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
let realOnRejected = () => {
setTimeout(() => { //onFulfilled or onRejected must not be called until the execution
context stack contains only platform code
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
switch (this.state) {
case FULFILLED:
realOnFulfilled();
break;
case REJECTED:
realOnRejected();
break;
case PENDING:
this._fulfilled_callback_list.push(() => {
realOnFulfilled();
})
this._rejected_callback_list.push(() => {
realOnRejected();
})
break;
}
});
return promise2;
}
3.3.6.resolvePromise
- 1.x和promise2相同,死循环
- 2.x是一个Promise 「这里是自己的这个promise」
- 3.x是对象或者函数
- 3.1.x有then方法,说明是一个thenable
- 3.2.x没有then,说明一个普通对象或者null
- 4.x是一个普通值
function resolvePromise(promise2, x, resolve, reject) {
//If promise and x refer to the same object, reject promise with a TypeError as the reason.
if (promise2 === x) {
reject(new TypeError('死循环'))
} else if (x instanceof Promise) { //If x is a promise, adopt its state
x.then(y => {
resolvePromise(promise2, y, resolve, reject);
}, reject);
} else if ((typeof x === 'object' && x !== null) || (typeof x === 'function')) { //Otherwise, if x is an object or function
let called = false;
try {
//Let then be x.then
let then = x.then;
if (typeof then === 'function') { //If then is a function
//call it with x as this
then.call(x, y => { //first argument resolvePromise
if (called) return;
called = true;
//If/when resolvePromise is called with a value y, run [[Resolve]](promise, y)
resolvePromise(promise2, y, resolve, reject);
}, r => { //second argument rejectPromise
if (called) return;
called = true;
reject(r); //If/when rejectPromise is called with a reason r, reject promise with r
})
} else { //If then is not a function, fulfill promise with x.
resolve(x);
}
} catch (error) { //If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason
if (called) return;
called = true;
reject(error);
}
} else { //If x is not an object or function, fulfill promise with x
resolve(x);
}
}
3.3.7.测试实现的promise
到这里,其实我们已经按照Promise A+规范实现了一个Promise,接下来我们测试一下自己写的promise
npm install promises-aplus-tests -g
Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd;
}
promises-aplus-tests promise.js
3.4.catch实现
catch (onRejected) {
return this.then(null, onRejected);
}
3.5.Promise.resolve实现
- 1.resolve方法是一个静态方法
- 2.resolve的参数可以是任何类型
- 3.resolve的返回结果是一个promise
static resolve(value) {
if (value instanceof Promise) return value;
return new Promise(resolve => {
resolve(value);
})
}
3.6.Promise.reject实现
- 1.reject方法是一个静态方法
- 2.reject的参数可以是任何类型
- 3.reject的返回结果是一个promise
static reject(reason) {
return new Promise((_, reject) => {
reject(reason);
})
}
3.7.Promise.all实现
可以解决异步并发问题,并且返回的结果按照调用的顺序进行存储。全部成功后才成功否则执行失败逻辑
- 1.all方法是一个静态方法
- 2.all的参数可以是任何类型的数组
- 3.all的返回结果是一个promise
static all(promiseList) {
return new Promise((resolve, reject) => {
let len = promiseList.length,
timers = 0;
result = [];
const resolveResult = (value, index) => {
result[index] = value;
if (++timers === len) {
resolve(result);
}
}
for (let i = 0; i < len; i++) {
const value = promiseList[i];
if (isPromise(value)) {
value.then(x => {
resolveResult(x, i);
}, reject)
} else {
resolveResult(value, i);
}
}
})
}
3.8.Promise.race实现
赛跑问题处理,无论成功还是失败,返回第一个返回的值
- 1.race方法是一个静态方法
- 2.race的参数可以是任何类型的数组
- 3.race的返回结果是一个promise
static race(promiseList) {
return new Promise((resolve, reject) => {
let len = promiseList.length;
if (len === 0) resolve();
else {
for (let i = 0; i < len; i++) {
Promise.resolve(promiseList[i]).then
(value => {
resolve(value)
}, reason => {
reject(reason);
})
}
}
})
}
3.9.finally实现
- 1.finally回调没有参数
- 2.finally返回的是一个promise
- 3.finally不管成功还是失败都会执行
- 4.finally成功的值不会作为下一个then的值
- 5.finally失败的值会终断链,他失败的值会作为下一次then的值
finally(callback) { //callback没有参数
return this.then(data => { //不管成功还是失败
callback都会执行
//callback执行,可能是一个promise需要等待他执行完
成
//成功需要将then的值传递下去,而不是callback的值
return Promise.resolve(callback()).then(_
=> data);
}, error => {
//需要调用resolve因为reject不会等待,然后在then中
将错误值抛出去
return Promise.resolve(callback()).then(_
=> {
throw error
});
});
}