Fork me on GitHub

JS-Promise

Promise,是一个代理对象,JavaScript 的异步操作解决方案,代表某个未来才会知道结果事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。

1、Promise 含义

一种异步编程解决方案
Promise 是一个对象,获取异步操作的消息

使用new生成Promise对象的实例,构造函数内部的代码会立即执行。

1
2
3
4
5
6
7
8
9
new Promise((resolve, reject) => {
console.log('new Promise');
resolve('success')
console.log('test')
})
console.log('finish');
//new Promise
//test
//finish

特点:
1、对象的状态不受外界影响。
pending(进行中),fulfilled(已成功),rejected(已失败)
只有异步操作的解构可以决定当前是那种状态,任何其他操作都没办法改变这个状态
2、一旦状态改变,就不会再变。
状态只能从 pending 变为 fulfilled,或是从 pending 变为 rejected
resolved 代表 fulfilled

缺点
1、中途无法取消
2、如果不设置回调函数,Promise 内部错误不会抛出到外部
3、当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)

2、基本用法

Promise 实例

1
2
3
4
5
6
7
const promise=new Promise((resolve ,reject)=>{
if(/*异步操作成功*/){
resolve(value)
}else{
reject(error)
}
})

resolvereject 函数是 js 引擎提供的。
promise 实例生成以后,可以使用 then 方法分别指定 resolved 状态和 rejected 状态的回调函数。

1
2
3
4
5
6
7
8
promise.then(
value=>{
//success
},
error=>{
//failure
}
)

第二个回调函数是可选的,两个回调函数的参数都是生成实例的时候传出的

1
2
3
4
5
6
7
8
9
10
11
const promise=new Promise((resolve ,reject)=>{
console.log('Promise')
resolve()
})
promise.then(()=>{
console.log('resolved')
})
console.log('hi')
//Promise
//hi
//resolved

实例立刻执行所以先输出Promisethen里面的函数要等到所有同步任务执行完才执行,所以先输出hi再输出 resolved
如果后面有多个then函数,会依次执行,第一个函数执行完后,第二个then的函数才会进入微任务队列。
图片加载异步操作

1
2
3
4
5
6
7
8
9
10
11
12
function loadImageAsync(url){
return new Promise((resolve ,reject)=>{
const image=new Image();
image.onload=function(){
resolve(image)
}
image.onerror=function(){
reject(new Error('Could not load image at'+url))
}
image.src=url
})
}

reject 函数的参数通常是 Error 对象。
resolve 函数的参数有可能是数据,也有可能是另一个Promise实例

1
2
3
4
5
6
7
8
const p1=new Promise((resolve ,reject)=>{
setTimeout(()=>reject(new Error('fail'),3000))
})
const p2=new Promise((resolve ,reject)=>{
setTimeout(()=>resolve(p1),1000)
})
p2.then(result=>console.log(result))
.catch(error=>console.log(error))

p2的状态一秒之后变为 resolve,返回的是p1p1定义时 3 秒后状态变为reject,所以再过两秒,p1变为reject。由于p2返回的是另一个Promise,所以p2的状态失效,下面的两个回调根据p1的执行结果执行。因此执行.catch,打印 Error:fail

注意,在创建Promise实例的时候调用函数resolve或是reject并不会终结 Promise的执行

1
2
3
4
5
6
new Promise((resolve ,reject)=>{
resolve(1);
console.log(2)
}).then(value=>console.log(value))
//2
//1

Promise实例会立刻执行,执行完,才会执行.then里面的语句,所以先 2 后 1。

3、Promise.prototype.then

then 方法是定义在 Promise 原型对象上的 为 Promise 实例状态变化添加回调函数。
then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。

1
2
3
4
5
6
7
new Promise((resolve,reject)=>{
if(成功){
resolve(1)
}else{
reject(2)
}
}).then((value,error)=>console.log(value, error))

then 方法返回一个新的Promise实例,因此可以采用链式写法

1
2
3
promise.then(result=>{
return result.data
}).then(data=>{})

如果then方法的回调函数返回的是Promise实例,后面的then方法会根据这Promise实例的状态变化才执行。

1
2
3
4
5
6
getJSON('/post/1.json').then(
post=>getJSON(post.commonURL)
).then(
newPost=>{console.log('resolved')},
error=>{console.log('rejected'+error)}
)

第一个then方法的回调函数返回一个新的Promise实例,第二个then会根据这个 Promise的执行结果来判断是执行resolved还是rejected

4、Promise.prototype.catch

用于指定发生错误时的回调函数
Promise实例执行的时候抛出的错误状态就会变为rejected,然后就会执行catch方法,并且错误会作为参数传入catch的回调函数。
另外 then 方法的回调运行时抛出错误也会被 catch 捕获

1
2
3
4
5
p.then(val=>console.log('fulfilled',val))
.catch(err=>console.log('rejected',err))
//等同于
p.then(val=>console.log('fulfilled',val))
.then(null ,err=>console.log('rejected',err))

reject方法,等同于抛出错误,throw Error
以下三种写法效果是一样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//1
new Promise((resolve ,reject)=>{
throw new Error('test')
}).catch(err=>console.log('rejected',err))
//2
new Promise((resolve ,reject)=>{
try{
throw new Error('test')
}catch(e){
reject(e)
}
}).catch(err=>console.log('rejected',err))
//3
new Promise((resolve ,reject)=>{
reject(new Error('test'))
}).catch(err=>console.log('rejected',err))

如果状态已经变为resolved再抛出错误是无效的

1
2
3
4
5
6
7
8
const Promise = new Promise(function(resolve, reject) {
resolve('ok');
throw new Error('test');
});
promise
.then(function(value) { console.log(value) })
.catch(function(error) { console.log(error) });
// ok

如果在Promise实例内部使用 try/catch,没有使用 catch 方法指定错误处理回调函数,抛出的错误不会返回到外部,即不会有任何反应

1
2
3
4
5
6
7
8
9
10
11
const  someAsync=function(){
return new Promise((resolve ,reject)=>{
resolve(x+2)
})
}
someAsync().then(
()=>console.log('everything is great')
)
setTimeout(() => { console.log(123) }, 2000);
//ReferenceError: x is not defined
//123

Promise 内部的语法错误,但是 123 还是打印出来,不会退出进程,终止整个脚本的执行
Promise 内部的错误不会影响到 Promise 外部的代码,通俗的说法就是“Promise 会吃掉错误”

catch 方法返回的还是一个 Promise,因此后面可以继续使用 then方法

1
2
3
4
5
6
7
8
Promise.resolve()
.catch(function(error) {
console.log('oh no', error);
})
.then(function() {
console.log('carry on');
});
// carry on

上面的代码因为没有报错,跳过了catch方法,直接执行后面的then方法。此时,要是then方法里面报错,就与前面的catch无关了。
catch 中也能抛出错误,并且可以被后面的 catch 捕获到。

5、Promise.prototype.finally

finally 方法用于指定不管 Promise 对象的状态如何都会执行的操作

1
2
3
4
promise
.then(result=>{})
.catch(error=>{})
.finally(()=>{})

finally 方法本质是 then 方法的特例

1
2
3
4
5
6
7
8
9
10
11
12
promise.finally(()=>{})
//等同于
promise.then(
result=>{
//语句
return result
},
error=>{
//语句
throw error
}
)

finally 实现

1
2
3
4
5
6
7
Promise.prototype.finally=function(callback){
let P =this.constructor
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
)
}

上面代码中,不管前面的 Promisefulfilled 还是 rejected,都会执行回调函数 callback
从上面的实现还可以看到,finally 方法总是会返回原来的值。

1
2
3
4
5
6
7
8
9
10
11
// 直接是resolved状态,resolve 的值是 undefined
Promise.resolve(2).then(() => {}, () => {})

// resolve 的值是 2
Promise.resolve(2).finally(() => {})

// reject 的值是 undefined
Promise.reject(3).then(() => {}, () => {})

// reject 的值是 3
Promise.reject(3).finally(() => {})

6、Promise.all()

用于将多个Promise 实例包装成一个Promise 实例

1
const  p=new Promise([p1,p2,p3])

Promise.all()接收一个数组作为参数,参数都是 Promise 实例,如果不是 Promise 实例会调用 Promise.resolve 方法转为 Promise 实例
p 的状态由 p1,p2,p3 共同决定,分为两种情况
p1,p2,p3 的状态都是 fulfilled 的时候,p 的状态才会变成fulfilled,此时 p1,p2,p3 的返回值组成一个数组传递给 p 的回调函数
p1,p2,p3 之中有一个变为rejected状态,p 就是rejected状态,第一个变为 rejected的实例的返回值作为参数传递给 p 的回调函数
注意,如果作为参数的的Promise实例里面定义了 catch,一但它进入 rejected 状态,并不会触发Promise.allcatch方法

1
2
3
4
5
6
7
8
9
10
11
12
13
const p1=new Promise((resolve ,reject)=>{
resolve('hello')
}).then(result=>{console.log('p1',result)})
.catch(err=>console.log('p1',err))
const p2=new Promise((resolve ,reject)=>{
throw new Error('出错了')
}).then(result=>{console.log('p2',result)})
.catch(err=>console.log('p2',err))
Promise.all([p1,p2])
.then(result=>{console.log('all',result)})
.catch(err=>console.log('all',err))
//p1 hello
// p2 Error: 出错了

p2 没有设置自身的catch方法时,就会调用 promise.allcatch方法

1
2
3
4
5
6
7
8
9
10
11
12
const p1=new Promise((resolve ,reject)=>{
resolve('hello')
}).then(result=>{console.log('p1',result)})
.catch(err=>console.log('p1',err))
const p2=new Promise((resolve ,reject)=>{
throw new Error('出错了')
}).then(result=>{console.log('p2',result)})
Promise.all([p1,p2])
.then(result=>{console.log('all',result)})
.catch(err=>console.log('all',err))
//p1 hello
// all Error: 出错了

7、Promise.race()

同样是将多个Promise实例包裹后返回一个实例

1
const p=new  Promise([p1,p2,p3])

只要 p1,p2,p3 中的任何一个实例中的状态首先发生变化,p 的状态就跟着变化
率先发生变化的实例的返回值作为参数传入 p 的回调函数
Promise.all一样如果传入的不是Promise的实例对象,就通过 Promise.resolve 转为Promise的实例

1
2
3
4
5
6
7
8
9
const p=Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise((resolve ,reject)=>{
setTimeout(reject(new Error('request timeout')),5000)
})
])
p.then(result=>console.log(result))
.catch(err=>console.log(err))
//Error: request timeout

5s 内 fetch 请求无法获取到返回结果,p 就会抛出超时错误

8、Promise.resolve()

将现有对象转为Promise对象

1
const  p=Promise.resolve($.ajax('/whatever.json'))

将 Jquery 生成的 deferred 对象转为Promise对象

1
2
3
Promise.resolve('foo')
//等同于
new Promise(resolve=>resolve('foo'))

Promise.resolve 方法分为四种情况
1、参数是一个Promise实例
直接将实例返回,不做更改
2、参数是一个thenable对象
thenable 对象是指具有then方法的对象

1
2
3
4
5
let  thenable={
then:function(resolve ,reject){
resolve(42)
}
}

Promise.resolve 会将这个对象转为Promise实例,然后立即执行thenable对象中的 then 方法

1
2
3
const p=Promise.resolve(thenable)
p.then(value=>console.log(value))
//42

3、参数不是含then方法的对象,或者根本不是对象
如果参数是原始类型的值,或者是一个不具有then方法的对象。Promise.resolve 方法返回一个Promise对象状态是 resolved,Promise.resolve 方法的参数会传给后面then的回调函数

1
2
3
const p=Promise.resolve('Hello')
p.then(s=>console.log(s))
//'Hello'

4、不带任何参数
Promise.resolve直接返回一个 resolved 状态的Promise对象
该对象时在本次事件循环结束的时候执行
setTimeout 在先出事件循环开始的时候执行

1
2
3
4
5
6
setTimeout(()=>console.log('three'),0)
Promise.resolve().then(()=>console.log('two'))
console.log('one')
//one
//two
//three

9、Promise.reject()

返回一个状态为 rejected 的Promise实例对象,

1
2
3
4
5
6
const p=Promise.reject('出错了')
//相当于
const p=new Promise((resolve ,reject)=>{
reject('出错了')
})
p.then(null ,err=>console.log(err))

注意Promise.reject 会将参数原封不动的传递给then方法的回调函数

1
2
3
4
5
6
7
const thenable={
then:function(){
reject('出错了')
}
}
Promise.reject(thenable).catch(res=>console.log(res===thenable))
//true

10、应用

Generator 函数与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
function getFoo(){
return new Promise((resolve ,reject)=>{
resolve('foo')
})
}
const g=function*(){
try{
const foo=yield getFoo()
}catch(e){
console.log(e)
}
}
function run(generator){
const it=generator();

function go(result){
if(result.done) return result.value;
return result.value.then(
value=>go(it.next(value)),
error=>go(it.throw(error))
)
}
go(it.next())
}
run(g)

上面代码的 Generator 函数 g 之中,有一个异步操作 getFoo ,它返回的就是一个Promise对象。函数 run 用来处理这个Promise对象,并调用下一个 next 方法。

手写 Promise

参考

基础版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyPromise{
state='pending';
value=null;
callbacks=[];
constructor(fn){
fn(this._resolve.bind(this))
}
then(onFulfilled){
if(this.state==='pending'){
this.callbacks.push(onFulfilled)
}else{
onFulfilled(this.value)
}
}
_resolve(newValue){
this.state='fulfilled';
this.value=newValue;
this.callbacks.forEach(cb=>cb(value))
}
}

增强版代码

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
  class MyPromise {
constructor(fn) {
this.callbacks = [];
this.state = "pending"; //状态
this.value = null; //回调返回结果

fn(this._resolve.bind(this), this._reject.bind(this))
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this._handle({
onRejected: onRejected || null,
onFulfilled: onFulfilled || null,
resolve,
reject
})
})

}
catch (onError) {
this.then(null, onError)
};
finally(onDone) {
if (typeof onDone !== 'function') {
return this.then();
}
let P = this.constructor;
return this.then(
value => P.resolve(onDone()).then(() => value),
reason => P.resolve(onDone()).then(() => reason)
)

};
static resolve(value) {
if (value && value instanceof MyPromise) {
return value;
} else if (value && typeof value === 'object' && typeof value.then === 'function') {
let {
then
} = value;
return new MyPromise(resolve => {
then(resolve)
})
} else if (value) {
return new MyPromise(resolve => resolve(value))
} else {
return new MyPromise(resolve => resolve())
}
}
static reject(value) {
if (value && typeof value === 'object' && typeof value.then === 'function') {
let then = value.then;
return new MyPromise((resolve, reject) => {
then(reject);
});
}
if (value) {
return new MyPromise((resolve, reject) => reject(value))
} else {
return new MyPromise((resolve, reject) => reject())
}
}
static all(promises) {
return new MyPromise((resolve, reject) => {
let fulfilledCount = 0;
const itemNum = promises.length;
const rets = Array.from({
length: itemNum
})
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(result => {
fulfilledCount++;
rets[index] = result;
if (fulfilledCount === itemNum) {
resolve(rets)
}
}, reason => reject(reason))
})
})
}
static race(promises) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
MyPromise.resolve(promises[i]).then(
ret => resolve(value),
reason => reject(reason)
)
}
})
}
_resolve(value) {
if (this.state === 'pending') {
if (value && (typeof value === 'object' || typeof value === 'function')) {
let {
then
} = value;
if (typeof then === 'function') {
then.call(value, this._resolve.bind(this), this._reject.bind(this))
return
}

}
this.state = 'fulfilled';
this.value = value;
this.callbacks.forEach(cb => this._handle(cb))
}
}
_reject(error) {
if (this.state === 'pending') {
this.state = 'rejected';
this.value = error;
this.callbacks.forEach(cb => this._handle(cb))
}
}
_handle(callback) {
if (this.state === 'pending') {
this.callbacks.push(callback);
return
}
let cb = this.state === 'fulfilled' ? callback.onFulfilled : callback.onRejected;
let next = this.state === 'fulfilled' ? callback.resolve : callback.reject;
if (!cb) {
next(this.value)
return
}
let ret;
try {
ret = cb(this.value)
} catch (e) {
ret = e;
// next = callback.reject
} finally {
next(ret)
}
}
}

符合 PromiseA+规范的实现

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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
const STATUS = {
PENDING: "pending",
FULFILLED: "fulfilled",
REJECTED: "rejected"
};
class MyPromise {
constructor(fn) {
this.resolved_callbacks = [];
this.rejected_callbacks = [];
this.state = STATUS.PENDING; //状态
this.value = null; //回调返回结果

try {
fn(this._resolve.bind(this), this._reject.bind(this));
} catch (e) {
this._reject.call(this, e);
}
}

then(onFulfilled, onRejected) {
const self = this;
let promise2;
//如果传入放入不是函数,错误处理
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (v) => v;
onRejected = typeof onRejected === "function" ? onRejected : (e) => e;

if (this.state === STATUS.PENDING) {
return (promise2 = new MyPromise((resolve, reject) => {
self.resolved_callbacks.push((value) => {
try {
let ret = onFulfilled(value);
this._resolvePromise(promise2, ret, resolve, reject);
} catch (reason) {
reject(reason);
}
});
self.rejected_callbacks.push((value) => {
try {
let ret = onRejected(value);
this._resolvePromise(promise2, ret, resolve, reject);
} catch (reason) {
reject(reason);
}
});
}));
}
if (this.state === STATUS.FULFILLED) {
return (promise2 = new MyPromise((resolve, reject) => {
// 异步执行onResolved
setTimeout(() => {
try {
let ret = onFulfilled(self.value);
this._resolvePromise(promise2, ret, resolve, reject);
} catch (reason) {
reject(reason);
}
});
}));
}
if (this.state === STATUS.REJECTED) {
return (promise2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
try {
let ret = onRejected(self.value);
this._resolvePromise(promise2, ret, resolve, reject);
} catch (reason) {
reject(reason);
}
});
}));
}
}
catch(onError) {
this.then(null, onError);
}
finally(onDone) {
if (typeof onDone !== "function") {
return this.then();
}
let P = this.constructor;
return this.then(
(value) => P.resolve(onDone()).then(() => value),
(reason) => P.resolve(onDone()).then(() => reason)
);
}
static resolve(value) {
if (this.class !== MyPromise.class) {
throw TypeError("incorrent-subclassing");
}
if (typeof this !== "function") {
throw TypeError("this is not a constructor");
}
if (value && value instanceof MyPromise) {
return value;
} else if (value && typeof value === "object" && typeof value.then === "function") {
let { then } = value;
return new MyPromise((resolve) => {
then(resolve);
});
} else {
return new MyPromise((resolve) => resolve(value));
}
}
static reject(value) {
if (this.class !== MyPromise.class) {
throw TypeError("incorrent-subclassing");
}
if (typeof this !== "function") {
throw TypeError("this is not a constructor");
}
if (value && typeof value === "object" && typeof value.then === "function") {
let then = value.then;
return new MyPromise((resolve, reject) => {
then(reject);
});
}
if (value) {
return new MyPromise((resolve, reject) => reject(value));
} else {
return new MyPromise((resolve, reject) => reject());
}
}
static all(promises) {
if (this.class !== MyPromise.class) {
throw TypeError("incorrent-subclassing");
}
if (!(typeof this === "function")) {
throw TypeError(`this is not a constructor`);
}
if (promises.length === undefined) {
return MyPromise.reject(new TypeError("argument is not iterable"));
}
if (promises.length == 0) {
return MyPromise.resolve([]);
}
return new MyPromise((resolve, reject) => {
const itemNum = promises.length;
const rets = Array.from({
length: itemNum
});
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
(result) => {
fulfilledCount++;
rets[index] = result;
if (fulfilledCount === itemNum) {
resolve(rets);
}
},
(reason) => reject(reason)
);
});
});
}
static race(promises) {
if (this.class !== MyPromise.class) {
throw TypeError("incorrent-subclassing");
}
if (!(typeof this === "function")) {
throw TypeError(`this is not a constructor`);
}
if (iterable.length === undefined) {
return MyPromise.reject(new TypeError("argument is not iterable"));
}
if (iterable.length == 0) {
return new MyPromise(function () {});
}
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
MyPromise.resolve(promises[i]).then(
(ret) => resolve(value),
(reason) => reject(reason)
);
}
});
}
_resolve(value) {
if (this.state === STATUS.PENDING) {
if (value instanceof Promise) {
return value.then(this._resolve, this._reject);
}
setTimeout(() => {
this.state = STATUS.FULFILLED;
this.value = value;
this.resolved_callbacks.forEach((cb) => cb(value));
this.resolved_callbacks = [];
});
}
}
_reject(error) {
if (this.state === STATUS.PENDING) {
setTimeout(() => {
this.state = STATUS.REJECTED;
this.value = error;
this.rejected_callbacks.forEach((cb) => cb(error));
this.rejected_callbacks = [];

});
}
}

_resolvePromise(promise2, ret, resolve, reject) {
let then;
let called = false; // then.call 的两个回调只能执行一次
const self = this;
//防止循环引用
if (promise2 === ret) {
return reject(new TypeError("Change cycle detected from promise!"));
}
//ret为Promise
if (ret instanceof MyPromise) {
if (ret.state ===STATUS.PENDING) {
ret.then((value) => self._resolvePromise(promise2, value, resolve, reject), reject);
} else {
ret.then(resolve, reject);
}
return;
}
//ret为对应或函数
if ((ret !== null && typeof ret === "object") || typeof ret === "function") {
try {
then = ret.then;
} catch (error) {
reject(error);
}
if (typeof then === "function") {
try {
then.call(
ret,
(data) => {
if (!called) {
self._resolvePromise(promise2, data, resolve, reject);
called = true;
}
},
(reason) => {
if (!called) {
reject(reason);
called = true;
}
}
);
} catch (e) {
if (!called) {
called = true;
reject(e);
}
}
} else {
resolve(ret);
}
} else {
resolve(ret);
}
}
}
-------------本文结束感谢阅读-------------