百行代码实现通过872条Promise/A+用例的Promise(简版)
前言
一直听说想成为一名高级前端程序员需要理解一些源码,那就从 Promise 开始吧,作者尽量用最少的语言让你理解 Promise
准备
Promises/A+原文[2]
Promises/A+译文[3]
安装 Promise 测试工具
npm i promises-aplus-tests -g
复制代码
运行测试工具,检测 Promise 是否符合规范
promises-aplus-tests [promise文件名]
复制代码
完整代码先过用例
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach((fn) => fn());
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
this.reject(e);
}
}
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value; // 如果onFulfilled不是函数则返回该数值
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err; // 如果onRejected不是函数,则抛出错误
};
}
let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.state === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
});
return promise2;
}
}
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x)
return reject(
new TypeError('Chaining cycle detected for promise #<Promise>')
);
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
let called;
try {
const then = x.then;
if (typeof then !== 'function') resolve(x);
else {
then.call(
x,
(value) => {
if (called) return;
called = true;
resolvePromise(promise2, value, resolve, reject);
},
(reason) => {
if (called) return;
called = true;
reject(reason);
}
);
}
} catch (err) {
if (called) return;
called = true;
reject(err);
}
} else {
resolve(x);
}
};
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise;
复制代码
完整代码127行,增加 Promise 测试代码一共 136 行代码。
如何测试
在 VS Code 新建文件 promise.jspromise.jspromise.js 文件
// promise代码
class Promise {
constructor() {}
then() {}
catch() {}
}
// 测试代码
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise;
复制代码
在 promise.jspromise.jspromise.js 文件所在目录打开终端,输入下面命令即可测试 Promise 是否符合规范
promises-aplus-tests promise.js
复制代码
后续讲解,不再解释测试代码,只讨论 Promise 代码了
请紧跟思路,本篇文章核心开始了
声明 Promise 类
Promise 常用的有 then 方法 和 catch,先用 ES6 语法声明一个 Promise 类
这点不难理解吧?
class Promise {
constructor() {}
then() {}
catch() {}
}
复制代码
constructor
正常使用 Promise 一般 如下图所示, new Promise(参数是一个函数)
let p1 = new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 1000);
});
复制代码
所以 在 Promise 类的 constructor 使用 executor 形参接收这个参数,这点不难理解吧?
class Promise {
constructor(executor) {}
then() {}
catch() {}
}
复制代码
继续:
executor 是用户输入的参数,咱们不能相信用户一定会使用一个函数作为 new Promise(参数) 对不对?
所以这里就需要判断一下 executor 是否是一个函数。
很好理解吧?
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
}
then() {}
catch() {}
}
复制代码
executor
constructor 这节已经知道 executor 是个函数了,executor 函数也是有参数的呀。
如下 Promise 使用代码
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
Math.random() > 0.5 ? resolve('正确') : reject('错误');
}, 1000);
});
p1.then((value) => {
console.log(value);
});
复制代码
image.png
Promises/A+ 规范中说:resolve 是进行成功的一系列操作,reject 是失败的一些操作,还有成功原因,失败原因?这些咱们的 Promise 都要有,都加上
resolve 和 reject
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
// promise 被解决时传递给解决回调的值
this.value = null;
// promise 被拒绝时传递给解决回调的值
this.reason = null;
// 成功的一系列操作
const resolve = () => {};
//失败的一些操作
const reject = () => {};
executor(resolve, reject);
}
then() {}
catch() {}
}
复制代码
状态
Promises/A+译文[4]
image.png
Promises/A+ 规范中说,Promise 要有 3 种状态。咱们在代码中将这三种状态加上,这很好理解吧
常量命名用大写,这点可以理解的
PENDING 、FULFILLED 和 REJECTED
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
}
then() {}
catch() {}
}
复制代码
要求说,Pending 状态只能去 Fulfilled 或者 Rejected 且不可变,这就需要一个变量记录 Promise 状态值, 并且状态值初始值为 Pending 这点可以理解吧
this.state
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
const resolve = () => {};
const reject = () => {};
executor(resolve, reject);
}
then() {}
catch() {}
}
复制代码
Pending 状态只能去 Fulfilled 或者 Rejected 意味着 resolve 和 reject 只有在 Pending 可以执行,没问题吧。
所以需要在 resolve 和 reject 函数中加判断
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
const resolve = () => {
// PENDING状态才能执行,执行完成修改状态为FULFILLED
if (this.state === PENDING) {
this.state = FULFILLED;
}
};
const reject = () => {
// PENDING状态才能执行,执行完成修改状态为 REJECTED
if (this.state === PENDING) {
this.state = REJECTED;
}
};
executor(resolve, reject);
}
then() {}
catch() {}
}
复制代码
执行完成功或者异常函数是不是要有成功或者异常数据呀,这些回调的值是不是需要保存到类中,在 then 方法中返回?
添加上
value 和 reason
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
const resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
// 解决时传递给解决回调的值
this.value = value;
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
// 拒绝时传递给解决回调的值
this.reason = reason;
}
};
executor(resolve, reject);
}
then() {}
catch() {}
}
复制代码
constructor 这就完成了吗?不,还差一步。
executor 是个函数,这在上文中有描述,但是函数有没有可能执行错误,直接执行这个函数报错,报错怎么处理?try/catch 大法喽
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
const resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
// 解决时传递给解决回调的值
this.value = value;
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
// 拒绝时传递给解决回调的值
this.reason = reason;
}
};
try {
// 如果函数顺利执行,执行函数
executor(resolve, reject);
} catch (error) {
// 函数抛出异常,将异常信息通过 reject 返回
reject(error);
}
}
then() {}
catch() {}
}
复制代码
Then
单独写 then 这个函数,暂时忽略 constructor 代码吧。代码太多容易混淆。读者觉得呢?
then() {}
复制代码
Promises/A+译文[5]
image.png
根据规范中规定 then
要有两个参数,并且这两个参数需要是函数,如果不是函数需要忽略
所以 then
代码如下;不难理解吧
then(onFulfilled, onRejected){
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}
}
复制代码
onFulfilled 和 onRejected
接着看规范描述
image.png
onFulfilled和onRejected调用次数不可超过一次,
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}
// 只执行一次
if (this.state === Promise.FULFILLED) {
onFulfilled(this.value);
}
if (this.state === Promise.REJECTED) {
onRejected(this.reason);
}
}
复制代码
resolve 支持异步
这样就可以了吗??不不不
如果 Promise 中 resolve 是在异步函数中执行的,目前我写的 Promise 代码中 console 并不会执行。
let p2 = new Promise((resolve) => {
setTimeout(() => {
resolve(2);
}, 1000);
});
p2.then((value) => {
console.log(value);
});
复制代码
原因是执行 .then
函数的时候 Promise
状态是 Pending
,当前我在 Promise.then
方法中只写了 状态为 FULFILLED
和 REJECTED
的处理
所以.then
函数还要处理状态位PENDING
的处理,pending 状态下,将.then 函数的入参先放在数组中,在异步执行 resolve 是调用
还有问题吗?
有的
then异步
console.log(1);
let p2 = new Promise((resolve) => {
resolve(4);
console.log(2);
});
p2.then((value) => {
console.log(value);
});
console.log(3);
// 1,2,3,4
复制代码
正常返回 1,2,3,4 现在我写的 promise 返回 1、2、4、3
什么原因呢?原因是 .then 中的函数立即执行了,这不符合标准呀,解决办法是给 .then 函数添加 setTimeout 模拟异步
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}
if (this.state === FULFILLED) {
setTimeout(() => {
onFulfilled(this.value);
});
}
if (this.state === REJECTED) {
setTimeout(() => {
onRejected(this.reason);
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
onFulfilled(this.value);
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
onRejected(this.reason);
});
});
}
let promise2 = new Promise(() => {});
return promise2;
}
}
复制代码
Promise 的数组需要在 constructor 中声明,并且在 resolve 中执行,所以代码 Promise 到这里全部代码如下:
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor) {
if (typeof executor !== 'function') {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach((fn) => fn());
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
this.reject(e);
}
}
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}
if (this.state === FULFILLED) {
setTimeout(() => {
onFulfilled(this.value);
});
}
if (this.state === REJECTED) {
setTimeout(() => {
onRejected(this.reason);
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
onFulfilled(this.value);
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
onRejected(this.reason);
});
});
}
}
}
复制代码
写到这里,我去测试了一下显示有 806
个异常;也就是说通过了 66
个测试用例。继续努力
then如何返回一个新的Promise
接着看规范描述:
then
方法必须返回一个 promise
对象
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}
if (this.state === FULFILLED) {
setTimeout(() => {
onFulfilled(this.value);
});
}
if (this.state === REJECTED) {
setTimeout(() => {
onRejected(this.reason);
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
onFulfilled(this.value);
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
onRejected(this.reason);
});
});
}
// 返回一个新的 promise 对象
let promise2 = new Promise(() => {});
return promise2;
}
复制代码
可以理解吧?每次 .then 都返回一个新的 promise 对象,.then 方法是不是就可以一直调用下去了
这里为什么不可以直接返回 this,比如 jQuery 不就是直接返回 this 实现链式调用的吗?
因为 promise 有 3 种状态,且状态不可逆,所以必须返回一个新的 promise 对象
then返回Promise解决过程
接着看规范描述:
- 如果
onFulfilled
或者onRejected
返回一个值x
,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)
- 如果
onFulfilled
或者onRejected
抛出一个异常e
,则promise2
必须拒绝执行,并返回拒因e
- 如果
onFulfilled
不是函数且promise1
成功执行,promise2
必须成功执行并返回相同的值 - 如果
onRejected
不是函数且promise1
拒绝执行,promise2
必须拒绝执行并返回相同的据因
第一句
需要确定, onFulfilled
或者 onRejected
返回一个值 x
要执行 Promise2
修改 then
代码如下:
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}
let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
const x = onFulfilled(this.value);
});
}
if (this.state === REJECTED) {
setTimeout(() => {
const x = onRejected(this.reason);
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
const x = onFulfilled(this.value);
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
const x = onRejected(this.reason);
});
});
}
});
return promise2;
}
}
复制代码
第二句
如果 onFulfilled
或者 onRejected
抛出一个异常 e
,则 promise2
必须拒绝执行,并返回拒因 e
使用 try/catch 捕捉 onFulfilled
或者 onRejected
抛出的异常
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}
let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
} catch (error) {
reject(error);
}
});
}
if (this.state === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
} catch (error) {
reject(error);
}
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
} catch (error) {
reject(error);
}
});
});
}
});
return promise2;
}
复制代码
第三句
如果 onFulfilled
不是函数且 promise1
成功执行, promise2
必须成功执行并返回相同的值
promise2 执行成功并返回值,这句简单,在返回 x 的地方直接 resolve(x) 不就可以了吗?
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}
let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolve(x);
} catch (error) {
reject(error);
}
});
}
if (this.state === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
// 这里直接 resolve 并并且返回 x
resolve(x);
} catch (error) {
reject(error);
}
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolve(x);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolve(x);
} catch (error) {
reject(error);
}
});
});
}
});
return promise2;
}
复制代码
如果 x 是基本数据类型可以,考虑一下,如果 x 是引用数据类型,是函数,甚至是 Promise 呢?
所以这里需要对 x 的数据类型判断
既然自成一体,索性增加一个方法执行这些 x 值
方法名为:resolvePromise
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}
let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (this.state === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
});
return promise2;
}
function resolvePromise(promise2, x, resolve, reject){
}
复制代码
resolvePromise
接下来开始写 resolvePromise 这个函数
判断 x 是不是 promise 自己
promise 不能循环调用,
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(
new TypeError('Chaining cycle detected for promise #<Promise>')
);
}
}
复制代码
判断 x 是不是引用数据类型
如果不是引用数据类型,直接执行 resolve(x)
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(
new TypeError('Chaining cycle detected for promise #<Promise>')
);
}
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
} else {
resolve(x);
}
}
复制代码
如果是引用数据类型,判断数据中是否有 then 这个属性,如果有 then 不是函数,直接执行 resolve(x)
这里解释一下:如果 then 是函数,表示 x 可能是 Promise 对象,需要特殊处理,如果不是函数,当作一般对象处理
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(
new TypeError('Chaining cycle detected for promise #<Promise>')
);
}
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
const then = x.then;
if (typeof then !== 'function') {
resolve(x);
} else {
}
} else {
resolve(x);
}
}
复制代码
当然,只要是代码就有可能出现异常,所以这里需要 try/catch 捕捉一些可能的异常
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(
new TypeError('Chaining cycle detected for promise #<Promise>')
);
}
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
try {
const then = x.then;
if (typeof then !== 'function') {
resolve(x);
} else {
}
} catch (err) {
reject(err);
}
} else {
resolve(x);
}
}
复制代码
如果 then 是函数
then 是函数,执行 then。因为此时的 then 是从 x 上获取的,所以要调用 call 方法将 then 函数的 this 重新指向 x
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(
new TypeError('Chaining cycle detected for promise #<Promise>')
);
}
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
try {
const then = x.then;
if (typeof then !== 'function') {
resolve(x);
} else {
then.call(
x,
(value) => {
resolvePromise(promise2, value, resolve, reject);
},
(reason) => {
reject(reason);
}
);
}
} catch (err) {
reject(err);
}
} else {
resolve(x);
}
}
复制代码
上述代码基本完成了 Promise 的功能,但是还有一点规范文档上说:
如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
这需要增加标识位 calledcalledcalled , called为true直接返回,
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x)
return reject(
new TypeError('Chaining cycle detected for promise #<Promise>')
);
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
let called;
try {
const then = x.then;
if (typeof then !== 'function') resolve(x);
else {
then.call(
x,
(value) => {
if (called) return;
called = true;
resolvePromise(promise2, value, resolve, reject);
},
(reason) => {
if (called) return;
called = true;
reject(reason);
}
);
}
} catch (err) {
if (called) return;
called = true;
reject(err);
}
} else {
resolve(x);
}
};
复制代码