当前位置: 代码迷 >> 综合 >> javascript基础-promise
  详细解决方案

javascript基础-promise

热度:52   发布时间:2023-12-11 23:24:11.0

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 方法有多个意义:

  1. then 函数只是在 promise 上注册了一些回调。
  2. 这些回调是接收 resolve 调用后的参数。
  3. 最终返回了一个新的 promise。
  4. 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 类似。暂时不实现这些细节。

  相关解决方案