promise实现了哪些功能?只有实现一个promise才能算真正的了解。。。
首先要理解一些概念。
- 异步执行
promise 的异步执行,具体哪些部分异步执行了?
promise 内的 resolve(作为一个回调函数)肯定是异步执行的,但是给 promise 直接传递的函数并没有异步执行。
then 的回调函数也异步执行,那是因为 resovle 异步执行了,而 then 函数本身是同步调用的。
const p = new Promise(resolve => {// 这个函数体同步执行// 这个 resolve 在 promise 内将被异步调用resolve();
});
// 这个 then 肯定是同步调用,因为 js 本身就是同步执行
p.then((v) => {// 这里的函数体是异步执行的,因为 resolve 是被异步调用的
});
- 返回值
promise 返回一个 promise 实例,调用 then 也同样返回一个 promise 实例。而 then 返回的是一个新的实例。
const p = new Promise(resolve => {
});
const _p = p.then((v) => {
});
// false
console.log(p === _p);
实现一个 promise
// 三种状态
const padding = 'padding';
const success = 'success';
const fail = 'fail';class MyPromise {// resolve 的值,实际上闭包即可,不需要专门维护value;// 三种状态state;// 注册 then 的 callbacktaskList = [];constructor(fn){// 创建 resolve 和 rejectconst resolve = (v) => {};const reject = (err) => {};// 默认状态this.state = padding;// 同步执行,但在 promise 内部只是注入了2个方法fn(resolve, reject);}
}// 普通调用,创建实例
const p = new MyPromise((resolve) => {resolve(1);
});
resolve 方法在 promise 内是异步调用;如果不调用 then,promise 的返回结果也会创建出来。这说明 resolve 方法:
const resolve = (v) => {// 模拟异步,实际上应该用微任务的 MutationObserversetTimeout(() => {this.value = v;});
};
原型方法:
then 方法有多个意义:
- then 函数只是在 promise 上注册了一些回调。
- 这些回调是接收 resolve 调用后的参数。
- 最终返回了一个新的 promise。
- then 不传任何参数等同于一次透传。
// 数字注释代表解决问题的序号
// 4
then(fn = v => v){// 3// 返回的是一个 promisereturn new MyPromise((resolve) => {// fn 肯定不是立即执行,所以放到一个 taskList 中// 这里是同步执行的,所以放在 promise 里也不影响,如果拿到 promise 外面不好组织// 1this.taskList.push((_v) => {// 这个匿名函数,实际上就是把 fn 封装了一层// 因为这里 resolve 需要拿到 fn 的执行结果// 它将在未来被调用,所以会拿到结果// 2const result = fn(_v);resolve(result);});});
}
回看 resolve,它应该解决的问题是,我注册了多个 then,那么应该依次执行 then 的回调。
且一旦调用 resolve,将更改 promise 的状态,且无法多次调用
const resolve = (v) => {// 如果状态被改变,则什么都不做if (this.state !== padding) {// 它当然需要同步判断return;}// 调用 resolve 时,锁定状态this.state = success;// 模拟异步,实际上应该用微任务的 MutationObserversetTimeout(() => {// taskList 是 注册 then 的 callback// task 是 then 方法中被封装的 fnthis.taskList.forEach(task => task(v));});
};
如果开发者延迟挂载 then 那么将导致 resolve 执行时,没有可以被通知的 taskList,所以延迟挂载 then 应该直接返回 value。
then(fn = v => v){// 如果 promise 已经是成功状态,则直接调用回调if (this.state === success) {// 直接调用// return fn(this.value);// 但 then 都是异步调用,所以用 promise.resolve 模拟const value = this.value;return new MyPromise((resolve) => {setTimeout(()=>{fn(value);resolve(value);});});}
}
此时的 promise 基本满足 resolve、then 的基本调用了。
静态方法:
Promise.resolve,返回一个 promise 实例,默认执行 resolve 方法。
static resolve(value){return new MyPromise((resolve) => {resolve(value);});
}
Promise.all,返回一个 promise 实例,当参数中所有的 promise 都 resolve 后,才会执行这个实例的 resolve。
static all(array){return new MyPromise((resolve, reject) => {const list = [];// 成功的数量let successIndex = 0;array.map(async (p, index) => {const v = await p.then();// 这里,如果是 catch 方法被触发,直接调用 rejectsuccessIndex++;list[index] = v;// 所有 promise 都成功了if (successIndex === array.length) {resolve(list);}});});
}
如果不用 async await,把 then 下面的代码放到 then 中执行即可。
p.then(v => {// 这里,如果是 catch 方法被触发,直接调用 rejectsuccessIndex++;list[index] = v;// 所有 promise 都成功了if (successIndex === array.length) {resolve(list);}
});
promise 实际还有很多功能和实现,比如 then 返回一个函数,或者返回一个对象且此对象拥有 then 方法,或则返回一个 promise,那么这个 promise 链还会延长。catch,流程与 resolve 类似。暂时不实现这些细节。