npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

promise-polyfill-ts

v1.0.1

Published

a promise created by typescript

Downloads

10

Readme

经常会有面试官问道“如何手动实现一个符合Promise/A+规范的简易版Promise”。当然通过面试不是我们的最终目的,熟练掌握其内部实现原理才是根本。
在写代码之前,我们需要知道Promise的三种状态,即pending, resoled, rejected。整个Promise的初始状态是pending,然后根据后续的处理情况状态会变为resoled或者rejected

enum Status {
    PENDING,
    RESOLVED,
    REJECTED
}

首先我们要弄清楚Promise的调用过程,在创建Promise的过程时,我们通常会new Promise(executor)。整个Promise的构造函数接受一个executor函数,该函数接收两个参数一个是resolve,一个是reject。
但是经过简单的分析我们可以知道resolve和reject也是两个函数,并且这两个函数应该是Promise类内部帮我们实现好的。

下面我们来看Promise内部需要哪些属性:

  • 我们需要一个存储当前Promise状态的status
  • 一个保存Promise成功时的值,方便我们传给resolve函数
  • 一个保存Promise失败时的值,方便我们传给reject函数
  • 一个存储Promise成功时回调函数的数组
  • 一个存储Promise失败时的回调函数的数组
private state: Status = Status.PENDING;
private value: V = null;
private reason: R = null;
private resolvedCallbacks: IStatusFunc<V>[] = [];
private rejectedCallbacks: IStatusFunc<R>[] = [];

我们也需要定义Promise内部的resolve和reject函数,这两个函数即分别执行成功和失败的回调函数。

// 将当前Promise的状态修改为resolved
// 并执行resolve时的回调函数
let resolve: IStatusFunc<V> = (value) =>{
    if (this.state === Status.PENDING) {
        this.state = Status.RESOLVED;
        this.value = value;
        this.resolvedCallbacks.forEach(callback => {
            callback(value);
        });
    }
}

// 将Promise的状态修改为rejected
// 并执行reject时的回调函数
let reject: IStatusFunc<R> = (reason) => {
    if (this.state === Status.PENDING) {
        this.state = Status.REJECTED;
        this.reason = reason;
        this.rejectedCallbacks.forEach(callback => {
            callback(reason);
        });
    }
}

接下来就是实现Promise中最为重要的一步,then方法,它可以实现链式调用。我们知道在jQuery中,链式调用的方式是在方法的尾部返回jQuery对象this。但显然这种方式在Promise中行不通,因为Promise的主要任务是解决异步操作,异步操作里面的return是无效的。
我们首先想到的就是在then中返回一个Promise对象,这样返回的Promise就可以继续调用其原型链上的then方法。但此时,如果单纯的执行onFullfilled或者onRejected回调函数的话,此时是不会有resolve或者reject这个过程的,所以为了让Promise有链式调用的功能,我们就需要有一个专门解析onFullFilledonRejected返回值得函数

/**
 * 解析onFullfilled或者onRejected的返回值
 * @param promise2 then函数返回的新的Promise
 * @param x onFullfilled或者onRejected的返回值
 * @param resolve 成功时的回调
 * @param reject  失败时的回调
 */
private resolvePromise(promise2: MyPromise<V, R>, x: any, resolve: IStatusFunc<V>, reject: IStatusFunc<R>) {
    // 禁止循环引用
    if (x === promise2) {
        throw new Error('Chaining cycle detected for promise');
    }
    // 是否已经调用过的标记
    let called: boolean = false;
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        try {
            // 如果x.then依旧是function,代表x是promise对象
            if (typeof x.then === 'function') {
                // x.then继续执行,第一个参数是this,后面依次是成功回调和失败的回调
                x.then.call(x, y => {
                    // 成功和失败只能调用一个
                    if (called) return;
                    called = true;
                    this.resolvePromise(promise2, y, resolve, reject);
                }, err => {
                    // 成功和失败只能调用一个
                    if (called) return;
                    called = true;
                    reject(err);
                });
            } else {
                resolve(x);
            }
        } catch(e) {
            if (called) return;
            called = true;
            reject(e);
        }
    } else {
        // 如果是普通类型,直接resolve
        resolve(x);
    }
}

then方法的实现也比较简单

/**
 * then方法
 * @param onFullfilled 成功的回调函数
 * @param onRejected 失败的回调函数
 */
then(onFullfilled: IStatusFunc<V>, onRejected?: IStatusFunc<R>) {

    // 返回Promise的目的是为了链式调用
    let promise2 = new MyPromise<V, R>((resolve: IStatusFunc<V>, reject: IStatusFunc<R>) => {
        if (this.state === Status.RESOLVED) {
            let x = onFullfilled(this.value);
            this.resolvePromise(promise2, x, resolve, reject);
        }
        if (this.state === Status.REJECTED) {
            let x = onRejected(this.reason);
            this.resolvePromise(promise2, x, resolve, reject);
        }
        if (this.state === Status.PENDING) {
            this.resolvedCallbacks.push(() => {
                let x = onFullfilled(this.value);
                this.resolvePromise(promise2, x, resolve, reject);
            });
            this.rejectedCallbacks.push(() => {
                let x = onRejected(this.reason);
                this.resolvePromise(promise2, x, resolve, reject);
            });
        }
    });
    return promise2;
}