Promise

描述

Promise 对象用于表示一个异步操作的最终完成(或失败)及其结果值。

三个状态

pending状态改变后就不能再变更状态

  1. pending
  2. fulfilled
  3. rejected

then catch finally

then

then 接受两个参数 第一个是rsolve的回调, 第二个是reject的回调,then默认返回新的promise

catch

实际是then方法的封装

finally

实际是then方法的封装

resolve reject

resolve

返回一个以给定值解析后的 Promise 对象。 如果值是一个Promise对象则直接返回该Promise。如果值带有then方法的对象,将跟随该对象到最终的结果并采用他的最终状态

reject

返回带有一个拒绝原因的Promise对象

all race

all

Promise.all() 方法接收一个 promise 的可迭代类型,并且只返回一个Promise实例, 那个输入的所有 promise 的 resolve 回调的结果是一个数组。这个Promise的 resolve 回调执行是在所有输入的 promise 的 resolve 回调都结束,或者输入的 iterable 里没有 promise 了的时候。它的 reject 回调执行是,只要任何一个输入的 promise 的 reject 回调执行或者输入不合法的 promise 就会立即抛出错误,并且 reject 的是第一个抛出的错误信息。

race

方法返回一个 promise,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。

any 非标准

该方法会返回一个新的 promise,一旦可迭代对象内的任意一个 promise 变成了兑现状态,那么由该方法所返回的 promise 就会变成兑现状态, 如果可迭代对象内的 promise 最终都没有兑现(即所有 promise 都被拒绝了),那么该方法所返回的 promise 就会变成拒绝状态

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
function MyPromise(fn) {
let state = 'pending'
let value = null
const callbacks = []

function resolve(newValue) {
const fn = () => {
if (state !== 'pending') return

if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
const { then } = newValue
if (typeof then === 'function') {
// newValue 为新产生的 MyPromise,此时resolve为上个 MyPromise 的resolve
// 相当于调用了新产生 MyPromise 的then方法,注入了上个 MyPromise 的resolve 为其回调
then.call(newValue, resolve, reject)
return
}
}
state = 'fulfilled'
value = newValue
handelCb()
}

setTimeout(fn, 0)
}
function reject(error) {
const fn = () => {
if (state !== 'pending') return

if (error && (typeof error === 'object' || typeof error === 'function')) {
const { then } = error
if (typeof then === 'function') {
then.call(error, resolve, reject)
return
}
}
state = 'rejected'
value = error
handelCb()
}
setTimeout(fn, 0)
}
function handelCb() {
while (callbacks.length) {
const fn = callbacks.shift()
handle(fn)
}
}

function handle(callback) {
if (state === 'pending') {
callbacks.push(callback)
return
}

const cb = state === 'fulfilled' ? callback.onFulfilled : callback.onRejected
const next = state === 'fulfilled' ? callback.resolve : callback.reject

if (!cb) {
next(value)
return
}
let ret;
try {
ret = cb(value)
} catch (e) {
callback.reject(e)
}
callback.resolve(ret);
}

this.then = function (onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
handle({
onFulfilled,
onRejected,
resolve,
reject,
})
})
}

this.catch = function (onError) {
return this.then(null, onError)
}

this.finally = function (onDone) {
this.then(onDone, onError)
}
// 执行
try {
fn(resolve, reject)
} catch(ex) {
reject(ex);
}
}

MyPromise.resolve = function (value) {
if (value && value instanceof MyPromise) {
return value
} if (value && typeof value === 'object' && typeof value.then === 'function') {
const { then } = value
return new MyPromise((resolve) => {
then(resolve)
})
} if (value) {
return new MyPromise(resolve => resolve(value))
}
return new MyPromise(resolve => resolve())
}

this.reject = function (value) {
return new MyPromise(((resolve, reject) => {
reject(value)
}))
}

MyPromise.all = function (arr) {
const args = Array.prototype.slice.call(arr)
return new MyPromise(((resolve, reject) => {
if (args.length === 0) return resolve([])
let remaining = args.length

function res(i, val) {
try {
if (val && (typeof val === 'object' || typeof val === 'function')) {
const { then } = val
if (typeof then === 'function') {
then.call(val, (val) => {
res(i, val)
}, reject)
return
}
}
args[i] = val
if (--remaining === 0) {
resolve(args)
}
} catch (ex) {
reject(ex)
}
}
for (let i = 0; i < args.length; i++) {
res(i, args[i])
}
}))
}

MyPromise.race = function (values) {
return new MyPromise(((resolve, reject) => {
for (let i = 0, len = values.length; i < len; i++) {
values[i].then(resolve, reject)
}
}))
}

错误处理

  1. try/catch

回调内的错误无法被捕获,会出现try/catch嵌套
示例

1
2
3
4
5
6
7
(async function () {
try {
Promise.reject(1).then(null, (e) => { throw e })
} catch (e) {
console.log(e);
}
})()