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 的 callback
    taskList = [];

    constructor(fn){
        //  创建 resolve 和 reject
        const 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) => {
    //  模拟异步,实际上应该用微任务的 MutationObserver
    setTimeout(() => {
        this.value = v;
    });
};

原型方法:

then 方法有多个意义:

  1. then 函数只是在 promise 上注册了一些回调。
  2. 这些回调是接收 resolve 调用后的参数。
  3. 最终返回了一个新的 promise。
  4. then 不传任何参数等同于一次透传。
//    数字注释代表解决问题的序号
//  4
then(fn = v => v){
    //  3
    //  返回的是一个 promise
    return new MyPromise((resolve) => {
        //  fn 肯定不是立即执行,所以放到一个 taskList 中
        //  这里是同步执行的,所以放在 promise 里也不影响,如果拿到 promise 外面不好组织
        //  1
        this.taskList.push((_v) => {
            //  这个匿名函数,实际上就是把 fn 封装了一层
            //  因为这里 resolve 需要拿到 fn 的执行结果
            //  它将在未来被调用,所以会拿到结果
            //  2
            const result = fn(_v);
            resolve(result);
        });
    });
}

回看 resolve,它应该解决的问题是,我注册了多个 then,那么应该依次执行 then 的回调。

且一旦调用 resolve,将更改 promise 的状态,且无法多次调用

const resolve = (v) => {
    //  如果状态被改变,则什么都不做
    if (this.state !== padding) {
        //    它当然需要同步判断
        return;
    }
    //  调用 resolve 时,锁定状态
    this.state = success;
    //  模拟异步,实际上应该用微任务的 MutationObserver
    setTimeout(() => {
        //  taskList 是 注册 then 的 callback
        //  task 是 then 方法中被封装的 fn
        this.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 方法被触发,直接调用 reject
            successIndex++;
            list[index] = v;
            //  所有 promise 都成功了
            if (successIndex === array.length) {
                resolve(list);
            }
        });
    });
}

如果不用 async await,把 then 下面的代码放到 then 中执行即可。

p.then(v => {
    //  这里,如果是 catch 方法被触发,直接调用 reject
    successIndex++;
    list[index] = v;
    //  所有 promise 都成功了
    if (successIndex === array.length) {
        resolve(list);
    }
});

promise 实际还有很多功能和实现,比如 then 返回一个函数,或者返回一个对象且此对象拥有 then 方法,或则返回一个 promise,那么这个 promise 链还会延长。catch,流程与 resolve 类似。暂时不实现这些细节。