promise

78 阅读1分钟

Promise通过构造函数的回调函数callback,以及callback的参数resolve和reject,Promise的实例是thenabel对象,then方法的参数是onFulfilled/onRejected函数,其参数是value/reason,取决于Promise的状态

promiseA+规范

1. 三种状态,流转如下

pending => resolve(value) => fulfilled

pending => reject(reason) => rejected

2. promise.then(onFulfilled, onRejected)

onFulfilled/onRejected若不是函数,则忽略

onFulfilled/onRejected函数在状态发生流转时被调用,且仅执行一次

onFulfilled/onRejected函数的执行环境是微任务里

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

``` js

promise.then(onResolved)

promise.then(onResolved)

promise.then(onResolved)

promise.then(onResolved)

// promise的状态从 pending 变成 fulfilled/rejected 后

// 同一个promise实例的所有的 onResolved/onRejected 回调函数都会一一执行

```

4. then的返回值是一个新的 promise 实例

5. resolvePromise

``` js

const PENDING = 'pending'

const FULFILLED = 'fulfilled'

const REJECTED = 'rejected'

class MPromise {

FULFILLED_CALLBACK_LIST = []

REJECTED_CALLBACK_LIST = []

_status = PENDING

constructor(fn) {

this.status = PENDING

this.value = null

this.reason = null

try {

fn(this.resolve.bind(this), this.reject.bind(this))

} catch(e) {

this.reject(e)

}

}

get stauts() {

return this._status

}

set status(newStatus) {

this._status = newStatus

switch(newStatus) {

case FULFILLED: {

this.FULFILLED_CALLBACK_LIST.forEach(cb => {

cb(this.value)

})

break

}

case REJECTED: {

this.REJECTED_CALLBACK_LIST.forEach(cb => {

cb(this.reason)

})

break

}

}

}

resolve(value) {

if (this.status === PENDING) {

this.status = FULFILLED

this.value = value

}

}

reject(reason) {

if (this.status === REJECTED) {

this.status = REJECTED

this.reason = REJECTED

}

}

then(onFulfilled, onRejected) {

const onRealFulfilled = this.isFunction(onFulfilled) ? onFulfilled : value => value

const onRealRejected = this.isFunction(onRejected) ? onRejected : reason => {

throw reason

}

const promise2 = new MPromise((resolve, reject) => {

const fulfilledMicrotask = () => {

queueMicrotask(() => {

try {

const x = onRealFulfilled(this.value)

this.resolvePromise(promise2, x, resolve, reject)

} catch(e) {

reject(e)

}

})

}

const rejectedMicrotask = () => {

queueMicrotask(() => {

try {

const x = onRejectedMicrotask(this.reason)

this.resolvePromise(promise2, x, resolve, reject)

} catch(e) {

reject(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(promise2, x, resolve, reject) {

if (promise2 === x) {

reject(new TypeError('promise和返回值重复'))

}

if (x instanceof MPromise) {

queueMicrotask(() => {

x.then(y => {

this.resolvePromise(promise2, y, resolve, reject)

}, reject)

})

} else if (typeof x === 'object' || this.isFunction(x)) {

if (x === null) {

resolve(x)

}

let then = null

try {

then = x.then

} catch(e) {

reject(e)

}

if (this.isFunction(then)) {

let called = false

try {

then.call(x, y => {

if (called) return

called = true

this.resolvePromise(promise2, y, resolve, reject)

}, r => {

if (called) return

called = true

reject(r)

})

} catch(e) {

if (called) return

reject(e)

}

} else {

resolve(x)

}

} else {

resolve(x)

}

}

static resolve(value) {

if (value instanceof MPromise) {

return value

}

return new MPromise(resolve => {

resolve(value)

})

}

static reject(reason) {

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

reject(reason)

})

}

isFunction(param) {

return typeof param === 'function'

}

}

```