手写Promise,一步步实现自己的Promise
- 一、什么是Promise
- 1Promise的使用方式(可能会发生的情况)
- 1.1 、只创建,不传入回调方法
- 1.2、创建 调用resolve 回调会抛错
- 1.3 、创建 调用reject回调,并且调用catch 或者then 方法传入了失败的回调, 返回的是 ==fulilled==状态
- 1.4、创建 调用reject回调,不调用catch, 返回的是==rejected==状态 与3不同
- 1.5、内部抛错 和4一样,此时会走catch方法
- 1.6、 存在异步函数 返回的是 ==pending==状态,不会走catch方法,也不会走finally方法
- 1.7、 return 返回 与6 相同 ==pending==状态,不会走then方法,也不会走finally方法
- 1.8 、多次调用resolve 或者 reject, 由第一个调用为准
- 二、开始实现
- 2.1 定义MyPromise
- 2.2 定义Promise返回的状态和数据
- 2.3 实现resolve / reject方法
- 2.4 抽离改变状态方法,解决promise 内部 throw的问题
- 2.5 实现Promise A+ 规范,then方法
- 2.6 解决异步函数内 resolve 无法被then捕捉问题
- 2.7 解决onFulfilled (this.#result) 过程中有报错的情况
- 2.8 解决返回的是promise的问题,解决promise 互操作性
- 2.9 加入微任务队列
- 2.10 实现catch方法
- 2.11 实现finally方法
- 2.12 实现静态resolve 方法
- 2.13 实现静态reject方法
- 2.14 实现all方法
一、什么是Promise
promis是异步工作解决方案,是callback回调的替代方案,通过new实例化对象,所以本质是一个构造方法。内部有三种状态: pending(进行中)、fulfilled(成功)、rejected(失败)。
提供的方法:
Promise A+ 规范.
- then () {} // 执行成功后的回调
- catch(onRejected) { } // Promise 失败时候的回调
- finally (onFinally) {} // Promise 不管失败还是成功的回调
- static resolve(result) { } // 更改Promise状态为 fulfilled, 执行then和finally方法结束当前Promise
- static reject (error) {} // 更改Promise状态为rejected,执行catch和finally方法结束当前Promise
- 其他,后面再说
1Promise的使用方式(可能会发生的情况)
1.1 、只创建,不传入回调方法
1.2、创建 调用resolve 回调会抛错
const p = new Promise((resolve, reject) => {
resolve(123);
}).then(res => {
// 成功返回后干嘛干嘛
}).finally(() => {
// 不管成功还是失败都返回,并且没有参数
})
1.3 、创建 调用reject回调,并且调用catch 或者then 方法传入了失败的回调, 返回的是 fulilled状态
const p = new Promise((resolve, reject) => {
reject(123);
}).catch(res => {
// 失败返回后干嘛干嘛
}).finally(() => {
// 不管成功还是失败都返回,并且没有参数
})
const p = new Promise((resolve, reject) => {
reject(123);
}).then(res => {
}, err => {
// 失败回调
})
1.4、创建 调用reject回调,不调用catch, 返回的是rejected状态 与3不同
1.5、内部抛错 和4一样,此时会走catch方法
const p = new Promise((resolve, reject) => {
throw 123;
})
1.6、 存在异步函数 返回的是 pending状态,不会走catch方法,也不会走finally方法
const p = new Promise((resolve, reject) => {
setTimeout(() => {
throw 123;
}, 0)
})
1.7、 return 返回 与6 相同 pending状态,不会走then方法,也不会走finally方法
const p = new Promise((resolve, reject) => {
return 123
})
1.8 、多次调用resolve 或者 reject, 由第一个调用为准
const p = new Promise((resolve, reject) => {
resolve(123);
reject(123);
})
二、开始实现
2.1 定义MyPromise
常规Promise 用法是 new 出来的,所以需要先顶一个构造器,并且传入的是一个回调函数,最终实现的是内部调用传入的方法与浏览器微任务有关,下文讲到,并且传入 Promise内部返回出来的resolve和reject方法
// 原始promise 使用方式
const promise = new Promise((resolve, rejeck) => {
// 这里可以传入参数
resolve(123);
})
// ------------------自己的promise 开始-------------------
// 定义回调函数,会被Promise自动执行
function callback (resolve, reject) {}
class MyPromise {
// jiejue
// executor 是外部传入的
constructor(executor) {
// 解决 目录1.1 报错问题,不传或者传的不是function
if (typeof executor !== 'function') {
throw new TypeError(`Promise resolver ${executor} is not a function`)
}
// 外部会调用方法并传入参数,不传就是undefind
const resolve = (data) => {}
const reject= (error) => {}
// 内部定义resolve/reject 返回出去
executor(resolve, reject)
}
}
const p = new MyPromise(callback);
2.2 定义Promise返回的状态和数据
promise 返回的一个是状态,一个是返回的结果
const PENDING= 'pending';
const FULFILLED= 'fulfilled';
const REJECTED= 'rejected';
class MyPromise {
// 私有属性外部不让用,用新出来的#前缀修饰
//用 typescript 可以用 private
// 默认是pending状态
#state = PENDING;
// 定义结果,默认是undefined
#result = undefined;
// 省略下面部分
}
2.3 实现resolve / reject方法
注意:由于promise内部resolve和reject和重复调用,并且状态只会被更新一次,需要判断一下当前状态
class MyPromise {
// 省略上卖弄部分
constructor(executor) {
// 省略上面
const resolve = (data) => {
// 判断是否被执行resolve或reject
if (this.#state !== PENDING) return;
// 状态置为fulfilled
this.#state = FULFILLED;
// 结果置为data
this.#result = data;
}
const reject= (error) => {
// 判断是否被执行resolve或reject
if (this.#state !== PENDING) return;
// 状态置为fulfilled
this.#state = REJECTED;
// 结果置为data
this.#result = error;
}
// 省略下面
}
}
2.4 抽离改变状态方法,解决promise 内部 throw的问题
// 由于更改状态的代码相似,抽一个方法出来
class MyPromise {
constructor(executor) {
// 省略上面
const resolve= (data) => {
this.#updateState(FULFILLED, data)
}
const reject= (error) => {
this.#updateState(REJECTED, error)
}
/* 解决 内部报错问题 用try catch 包裹
new Promise(() => {
throw 123
})
*/
// 注意:这里只能捕捉到同步错误,内部如果是setTimeout 返回的异步代码是捕捉不到的
try {
executor(resolve, reject)
} catch (error) {
// 报错 内部调用reject方法
reject(error)
}
}
// 传入状态和 结果// 统一入口,下面会用到
#updateState (state, result) {
if (this.#state !== PENDING) return;
this.#state = state;
this.#result = result;
}
}
注意:这里实现的效果有
- 目录1.1 报错效果
- 目录1.8重复调用resolve只会更改一次状态效果
- 目录throw后 会走catch方法效果,catch方法下面实现
2.5 实现Promise A+ 规范,then方法
Promise A+ 规范 并未说明 怎么样算一个Promise,只需要一个对象或者方法带有then方法,他就认为你就是promise,就可以和自生交互
then 方法 特点
- 有2个参数 onFulfilled 和 onRejected, 可以是任意值
- 如果onFulfilled/onRejected 传入的不是一个函数,那么此时的状态和当前Promise一致
- 返回的是一个新的promise
class MyPromise {
// 有2个参数 onFulfilled 和 onRejected
then (onFulfilled, onRejected) {
// 返回一个新的promise,
return new MyPromise((resolve, reject) => {
// 1.解决什么时候调用onFulfilled / onRejected
if (this.#state === FULFILLED) {
// onFulfilled 可以是任意值,需要判断是否是函数
if (typeof onFulfilled === 'function') {
onFulfilled(this.#result)
} else {/*先留着*/ }
} else if (this.#state === REJECTED) {
/ / onRejected可以是任意值,需要判断是否是函数
if (typeof onRejected=== 'function') {
onRejected(this.#result)
} else {/*先留着*/ }
} else {
// 如果这里是异步的 这么办?????
/*
setTimeout(() =. {
resolve(12323)
}, 1000)
*/
}
})
}
}
const p = new MyPromise((resolve, reject) => {
resolve(123)
})
p.then((res) => {
console.log('promise 成功', res)
}, (err) => {
console.log('promise 失败', err)
})
2.6 解决异步函数内 resolve 无法被then捕捉问题
要解决2.5问题,
- 首先要知道 什么时候执行onFulfilled/onRejected方法??
回答是当状态变化的时候,也就是#updateState里面去执行 - 状态变化时怎么知道 2.5 提到 onFulfilled/onRejected 方法,怎么知道返回新的promise里面的resolve/reject方法?
方法是 先找个地方存起来
class MyPromise {
// 保存当前then方法里面的方法地址,考虑到then方法可以被多次调用,并且每个then返回 结果都市一样的,这里要设置成一个数组
#currentThenParams = [];
#handlerThenFn () {
// 当前状态没有变更就不执行
if (this.#state === FULFILLED) return;
while (this.#currentThenParams.length) {
// 每次弹出一个去执行
const { onFulfilled,
onRejected,
resolve,
reject } = this.#currentThenParams.shift();
}
if (this.#state === FULFILLED) {
// onFulfilled 可以是任意值,需要判断是否是函数
if (typeof onFulfilled === 'function') {
// 调用onFulfilled 会有返回值,需要重新resolve出去
const result = onFulfilled(this.#result);
resolve(result )
} else {
// 走到这里说明传进来的是其他值,应该和resolve返回一致 的结果
resolve(this.#result)
}
} else if (this.#state === REJECTED) {
// onRejected可以是任意值,需要判断是否是函数
if (typeof onRejected=== 'function') {
// 调用onFulfilled 会有返回值,需要重新reject出去
const result = onRejected(this.#result)
reject(result )
} else {
// 走到这里说明传进来的是其他值,应该和resolve返回一致 的结果
reject(this.#result)
}
}
}
// 传入状态和 结果// 统一入口,下面会用到
#updateState (state, result) {
if (this.#state !== PENDING) return;
this.#state = state;
this.#result = result;
this.#handlerThenFn()
}
// 有2个参数 onFulfilled 和 onRejected
then (onFulfilled, onRejected) {
// 返回一个新的promise,
return new MyPromise((resolve, reject) => {
// 把所有方法的地址存起来
this.#currentThenParams.push({
onFulfilled,
onRejected,
resolve,
reject
})
this.#handlerThenFn()
})
}
}
const p = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(123)
})
})
p.then((res) => {
console.log('promise 成功', res)
}, (err) => {
console.log('promise 失败', err)
}).then((res) => {
console.log('promise 成功11', res)
}, (err) => {
console.log('promise 失败11', err)
})
到这里已经实现了可以链式调用then方法了,而且能顺利调用每一个回调,但是还有不少缺陷
- const result = onRejected(this.#result) 假如传入的是新promise,那么result 是一个promise,不能直接返回
- 假如onRejected(this.#result) 执行时候报错了,那就需要reject 出去,这个不会执行
- Promise应该是一个微任务,到这里度只是同步执行,用console.log 可以试验一下
console.log('我是最先执行的')
new MyPromise((resolve) => {
resolve('我是MyPromise')
}).then(res => {
console.log(res )
})
console.log('照道理我是第二个执行的')
2.7 解决onFulfilled (this.#result) 过程中有报错的情况
用try catch 包裹即可
onRejected 同理
if (typeof onFulfilled === 'function') {
try {
// 调用onFulfilled 会有返回值,需要重新reject出去
const result = onFulfilled(this.#result)
resolve(result ); // 这里是resolve
} catch (error) {
reject(error) // 这里是reject
}}
}
if (typeof onRejected=== 'function') {
try {
// 调用onFulfilled 会有返回值,需要重新reject出去
const result = onRejected(this.#result)
resolve(result ); // 这里resolve
} catch (error) {
reject(error); // reject
}}
}
2.8 解决返回的是promise的问题,解决promise 互操作性
Promise A+ 规范里面提到的,只要你带有then方法,那就可以和Promise互操作
首先定义一个类promise方法入口,统一判断是否是promise
然后在 onFulfilled(this.#result) 返回后 先去判断一下是否是promise
class MyPromise {
// 省略上面
// 判断是否是一个类promise
// 判断不管你是一个对象还是一个方法,只要带有then方法,就可以互操作
#isPromiseLike(result) {
if (result !== null && (typeof result === 'object' || typeof result === 'function')) {
if (typeof result.then === 'function') {
return true
}
}
return false
}
// 省略下面
// 改造
try {
// 调用onFulfilled 会有返回值,需要重新reject出去
const result = onRejected(this.#result);
// Promise A+ 规范 说只要是 带有then方法 就 是类Proimise,
if (this.$isPromiseLike(result)){
// 执行then方法
data.then(resolve, reject)
} else {
reject(result ); // 这里不用变,还是reject
}
}
}
// 测试一下
setTimeout(() => {
console.log('我应该是最后一个执行')
}, 0)
const p1 = new MyPromise((resolve) => {
resolve('我是MyPromise')
}).then(res => {
return new Promise((resolve) => {
resolve('我是系统promise resolve的数据')
})
}).then(res => {
// 照道理这里应该打印 我是系统promise resolve的数据
console.log(res )
})
const p2 = new MyPromise((resolve) => {
resolve('我是MyPromise')
}).then(res => {
const obj = {
then: (resolve, reject) => {
resolve('我是一个obj上的一个then方法')
}
}
return obj
}).then(res => {
// 照道理这里应该打印 我是一个obj上的一个then方法
console.log(res )
})
console.log('我是同步代码,我应该最先被执行')
会发现最后一行的打印 console.log('我是同步代码,我应该最先被执行') 并没有被优先执行
原因是没有加入到微任务队列中去
2.9 加入微任务队列
定义joinToMicroTask
#joinToMicroTask(fn) {
// 假如是node环境 判断 process
if (typeof process === 'object' && typeof process.nextTick === 'function') {
process.nextTick(fn)
} else if (typeof MutationObserver === 'function') { // 判断是浏览器环境, 用 MutationObserver 实现
// 注册一个观察器
const observer = new MutationObserver(fn);
// 定义一个文本节点, 初始值为1
const textNode= document.createTextNode('1');
// 观察文本节点的变化
observer.observe(textNode, {
characterData: true
})
textNode.data = '2'
}
}
#handlerThenFn () {
// 省略上面
const { onFulfilled,
onRejected,
resolve,
reject } = this.#currentThenParams.shift();
}
this.#joinToMicroTask(() => {
if (typeof onFulfilled === 'function') {
// 下面省略
})
}
2.10 实现catch方法
mdn 上描述catch方法
意思就是说就调用then方法
// 直接效用then方法即可
catch (onRejected) {
return this.then(undefined, onRejected)
}
// 测试
new MyPromise((resolve,reject) => {
reuject(123123)
}).catch ((err) => {
console.log('catch被执行', err)
})
2.11 实现finally方法
mdn 上描述finally方法
意思是说,直接调用then方法, 然后把onFinally 传进去,并且onFinally的回调函数 是没有参数 ,而且和原始promise状态一致,也就是直接把原始promise的数据返回即可
// 直接效用then方法即可
// finally
finally (onFinally) {
return this.then((data) => {
// 这里没有参数的
onFinally();
// 返回的状态与原始promise状态一致,直接把当前data返回
return data;
}, (error) => {
onFinally();
// 返回的状态与原始promise状态一致,抛个错, 这一步会被上面try catch 捕捉到
throw error
})
}
// 测试
new MyPromise((resolve,reject) => {
// resolve(123);
reuject(123123)
}).finally(() => {
console.log('finally被执行')
})
2.12 实现静态resolve 方法
意思是,首先是一个静态方法,意味着是MyPromise.resolve 调用
如果resolve传入的是一个promise,那么直接返回传入的promise
如果是类Promise,那么就最后会返回一个promise,并且 执行传入的值上面的then方法
如果是字符串,number等其他数据,那就返回promise 返回传入的数据
static resolve (data) {
// 如果是我们自己写的Oromise, 直接返回即可
if (data instanceof MyPromise) return data;
// 由于静态方法里面无法获取实例方法, 那我们创建一个Promise
let _resolve, _reject;
const p = new MyPromise((resolve, reject) => {
_resolve = resolve;
_reject = reject;
})
// 此时p 就是一个实例
if (p.#isPromiseLike(data)) {
data.then(_resolve, _reject)
} else {
_resolve(data)
}
return p
}
// 测试
const p = new Promise((resolve) => {
resolve(123)
})
const p2 = new Promise((resolve) => {
resolve(123)
})
const obj = {
then((resolve, reject) => {
resolve('obj')
})
}
console.log(MyPromise.resolve(p).then(data => {console.log(data)}))
console.log(MyPromise.resolve(p2) === p2)
console.log(MyPromise.resolve(obj).then(data => {console.log(data)}))
console.log(MyPromise.resolve(12313123123).then(data => {console.log(data)}))
2.13 实现静态reject方法
mdn 上描述reject方法
意思是,不传传进来的是什么,我都返回一个拒绝的promse
static reject (error) {
return new MyPromise((resolve, reject) => {
// 不传传进来什么,我都拒绝
reject(error)
})
}
2.14 实现all方法
mdn 上描述all方法
意思是,接受一个可迭代对象,(可能是Set,Array等),返回一个promise。
当所有都返回成功,那就返回成功
只要有一个失败,那就返回失败的原因
// 接受一个可迭代对象
static all (iteratorObj) {
// 判断是否可迭代,不可迭代抛错
if (!(iteratorObj != null && typeof iteratorObj[Symbol.iterator] === 'function')) {
throw new TypeError(`${iteratorObj} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
// 首先需要一个Promise,并且最终会被返回
let _resolve, _reject; // 先不管,先保存下来
const p = new MyPromise((resolve, reject) => {
_resolve = resolve;
_reject = reject;
})
// 可迭代对象肯定能被for of 遍历,但拿不到下标,需要外部定义一个下标,在遍历的时候手动维护
// promise的返回值只有执行完成后才能拿到,定义一个数组,用于保存成功的promise返回值
let count = 0;
let successCount = 0; // 成功的次数
const successArr = [];
for (const item of iteratorObj) {
console.log(item);
// 因为promise是异步的,不知道啥时候返回,不能使用count作为下标
// 作用域种保存当前promise执行后需要塞到数组下标的那个位置
const index = count;
count++;
// 先变成一个promise
MyPromise.resolve(item).then(data => {
// 把数据塞到保存的对应下标的位置
successArr[index] = data;
successCount++
// 当所有的promise 全都完成的时候就节俗promise
// 也就是成功的数组长度=== count, bindqie
if (successCount === count) {
_resolve(successArr)
}
}, error => {
// 只要有一个失败了,那就借宿了
_reject(error)
})
}
// 如果传入的对象没有什么可以迭代 ,那就返回空数组
if (count === 0) {
_resolve([])
}
return p
}
// 测试
const p1 = new Promise((resolve) => {
resolve(123)
})
const p2 = new MyPromise((resolve) => {
setTimeout(() => {
resolve(123)
}, 1000)
})
const p3 = new MyPromise((resolve, reject) => {
reject(123)
})
MyPromise.all([123, null, p1, p2, p3]).then(rs => {
console.log(rs)
}).catch(err => console.log('有一个拒绝了', err))
MyPromise.all(new Set([123, null, p1, p2])).then(rs => {
console.log(rs)
})
其他方法 race,any,allSettled 原理差不多,这里不写了。
附上完整源码
const PENDING = 'pending';
const FULFILLED= 'fulfilled';
const REJECTED= 'rejected';
class MyPromise {
// 私有属性外部不让用,用新出来的#前缀修饰
//用 typescript 可以用 private
// 默认是pedding状态
#state = PENDING;
// 定义结果,默认是undefined
#result = undefined;
// 保存当前then方法里面的方法地址
#currentThenParams = [];
// executor 是外部传入的
constructor(executor) {
// 解决 目录1.1 报错问题
if (typeof executor !== 'function') {
throw new TypeError(`Promise resolver ${executor} is not a function`)
}
// 外部会调用方法并传入参数,不传就是undefind
const resolve= (data) => {
this.#updateState(FULFILLED, data)
}
const reject= (error) => {
this.#updateState(REJECTED, error)
}
/* 解决 内部报错问题 用try catch 包裹
new Promise(() => {
throw 123
})
*/
// 注意:这里只能捕捉到同步错误,内部如果是setTimeout 返回的异步代码是捕捉不到的
try {
executor(resolve, reject)
} catch (error) {
// 报错 内部调用reject方法
reject(error)
}
}
// 传入状态和 结果// 统一入口,下面会用到
#updateState (state, result) {
if (this.#state !== PENDING) return;
this.#state = state;
this.#result = result;
this.#handlerThenFn()
}
// 判断是否是一个类promise
// 判断不管你是一个对象还是一个方法,只要带有then方法,就可以互操作
#isPromiseLike(result) {
if (result !== null && (typeof result === 'object' || typeof result === 'function')) {
if (typeof result.then === 'function') {
return true
}
}
return false
}
#joinToMicroTask(fn) {
// 假如是node环境 判断 process
if (typeof process === 'object' && typeof process.nextTick === 'function') {
process.nextTick(fn)
} else if (typeof MutationObserver === 'function') { // 判断是浏览器环境, 用 MutationObserver 实现
// 注册一个观察器
const observer = new MutationObserver(fn);
// 定义一个文本节点, 初始值为1
const textNode= document.createTextNode('1');
// 观察文本节点的变化
observer.observe(textNode, {
characterData: true
})
textNode.data = '2'
} else {
alert(1)
}
}
#handlerThenFn () {
// 当前状态没有变更就不执行
if (this.#state === PENDING) return;
while (this.#currentThenParams.length) {
// 每次弹出一个去执行
const { onFulfilled,
onRejected,
resolve,
reject } = this.#currentThenParams.shift();
this.#joinToMicroTask(() => {
if (this.#state === FULFILLED) {
// onFulfilled 可以是任意值,需要判断是否是函数
if (typeof onFulfilled === 'function') {
const result = onFulfilled(this.#result);
if (this.#isPromiseLike(result)) {
result.then(resolve, reject)
} else {
resolve(result)
}
} else {
// 走到这里说明传进来的是其他值,应该和resolve返回一致 的结果
resolve(this.#result)
}
} else if (this.#state === REJECTED) {
// onRejected可以是任意值,需要判断是否是函数
if (typeof onRejected=== 'function') {
const result = onRejected(this.#result)
resolve(result)
} else {
// 走到这里说明传进来的是其他值,应该和resolve返回一致 的结果
reject(this.#result)
}
}
})
}
}
// 有2个参数 onFulfilled 和 onRejected
then (onFulfilled, onRejected) {
// 返回一个新的promise,
return new MyPromise((resolve, reject) => {
// 把所有方法的地址存起来
this.#currentThenParams.push({
onFulfilled,
onRejected,
resolve,
reject
});
this.#handlerThenFn()
})
}
// 直接效用then方法即可
catch (onRejected) {
return this.then(undefined, onRejected)
}
// finally
finally (onFinally) {
return this.then((data) => {
// 这里没有参数的
onFinally();
// 返回的状态与原始promise状态一致,直接把当前data返回
return data;
}, (error) => {
onFinally();
// 返回的状态与原始promise状态一致,抛个错, 这一步会被上面try catch 捕捉到
throw error
})
}
static resolve (data) {
// 如果是我们自己写的Oromise, 直接返回即可
if (data instanceof MyPromise) return data;
// 由于静态方法里面无法获取实例方法, 那我们创建一个Promise
let _resolve, _reject;
const p = new MyPromise((resolve, reject) => {
_resolve = resolve;
_reject = reject;
})
// 此时p 就是一个实例
if (p.#isPromiseLike(data)) {
data.then(_resolve, _reject)
} else {
_resolve(data)
}
return p
}
static reject (error) {
return new MyPromise((resolve, reject) => {
// 不传传进来什么,我都拒绝
reject(error)
})
}
// 接受一个可迭代对象
static all (iteratorObj) {
// 判断是否可迭代,不可迭代抛错
if (!(iteratorObj != null && typeof iteratorObj[Symbol.iterator] === 'function')) {
throw new TypeError(`${iteratorObj} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
// 首先需要一个Promise,并且最终会被返回
let _resolve, _reject; // 先不管,先保存下来
const p = new MyPromise((resolve, reject) => {
_resolve = resolve;
_reject = reject;
})
// 可迭代对象肯定能被for of 遍历,但拿不到下标,需要外部定义一个下标,在遍历的时候手动维护
// promise的返回值只有执行完成后才能拿到,定义一个数组,用于保存成功的promise返回值
let count = 0;
let successCount = 0; // 成功的次数
const successArr = [];
for (const item of iteratorObj) {
console.log(item);
// 因为promise是异步的,不知道啥时候返回,不能使用count作为下标
// 作用域种保存当前promise执行后需要塞到数组下标的那个位置
const index = count;
count++;
// 先变成一个promise
MyPromise.resolve(item).then(data => {
// 把数据塞到保存的对应下标的位置
successArr[index] = data;
successCount++
// 当所有的promise 全都完成的时候就节俗promise
// 也就是成功的数组长度=== count, bindqie
if (successCount === count) {
_resolve(successArr)
}
}, error => {
// 只要有一个失败了,那就借宿了
_reject(error)
})
}
// 如果传入的对象没有什么可以迭代 ,那就返回空数组
if (count === 0) {
_resolve([])
}
return p
}
}
export default MyPromise