Promise标准及实现

Promise标准解读

  1. 只有一个then方法,没有catch,race,all等方法,甚至没有构造函数
    Promise标准中仅指定了Promise对象的then方法的行为,其它一切我们常见的方法/函数都并没有指定,包括catch,race,all等常用方法,甚至也没有指定该如何构造出一个Promise对象,另外then也没有一般实现中(Q, $q等)所支持的第三个参数,一般称onProgress

  2. then方法返回一个新的Promise

  3. 不同Promise的实现需要可以相互调用(interoperable)

  4. Promise的初始状态为pending,它可以由此状态转换为fulfilled(本文为了一致把此状态叫做resolved)或者rejected,一旦状态确定,就不可以再次转换为其它状态,状态确定的过程称为settle

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
156
try {
module.exports = Promise
} catch (e) { }


function Promise(exec) {
var self = this;
self.status = 'pending';
self.onResolvedCallback = [];
self.onRejectedCallback = [];

function resolve(value) {
if (value instanceof Promise) {
return value.then(resolve, reject);
}
setTimeout(function () {
if (self.status === 'pending') {
self.status = 'resolved';
self.data = value;
for (var i = 0; i < self.onResolvedCallback.length; i++) {
self.onResolvedCallback[i](value);
}
}
})
}
function reject(reason) {
setTimeout(function () {
if (self.status === 'pending') {
self.status = 'rejected';
self.data = reason;
for (var i = 0; i < self.onRejectedCallback.length; i++) {
self.onRejectedCallback[i](reason);
}
}
})
}

try {
exec(resolve, reject);
} catch (error) {
reject(err)
}
}

function resolvePromise(promise2, x, resolve, reject) {
var then
var thenCanceldOrThrow = false

if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise!'))
}
if (x instanceof Promise) {
if (x.status === 'pending') {
x.then(function (v) {
resolvePromise(promise2, v, resolve, reject);
}, reject);
} else {
x.then(resolve, reject);
}
return
}

if ((x !== null) && ((typeof x === 'object') || (typeof x === 'function'))) {
try {
then = x.then
if (typeof then === 'function') {
then.call(x, function rs(val) {
if (thenCanceldOrThrow) return
thenCanceldOrThrow = true;
return resolvePromise(promise2, val, resolve, reject)
}, function rj(reason) {
if (thenCanceldOrThrow) return
thenCanceldOrThrow = true;
return reject(reason);
})
} else {
resolve(x)
}
} catch (err) {
if (thenCanceldOrThrow) return
thenCanceldOrThrow = true;
return reject(err);
}
} else {
resolve(x)
}
}

Promise.prototype.then = function (onResolved, onRejected) {
var self = this;
var promise2;

onResolved = typeof onResolved === 'function' ? onResolved : function (value) { return value };
onRejected = typeof onRejected === 'function' ? onRejected : function (reason) { throw reason };

if (self.status === 'resolved') {
return promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
var x = onResolved(self.data);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
})
})
}

if (self.status === 'rejected') {
return promise2 = new Promise(function (resolve, reject) {
setTimeout(function (reason) {
try {
var x = onRejected(self.data);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
})
})
}

if (self.status === 'pending') {
return promise2 = new Promise(function (resolve, reject) {
self.onResolvedCallback.push(function (value) {
try {
var x = onResolved(value);
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error);
}
});
self.onRejectedCallback.push(function (reason) {
try {
var x = onRejected(reason);
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error);
}
});
})
}
}


Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected)
}

Promise.deferred = Promise.defer = function () {
var dfd = {}
dfd.promise = new Promise(function (resolve, reject) {
dfd.resolve = resolve
dfd.reject = reject
})
return dfd
}