使用 ES6 简单实现一个promise

本文深入探讨了自定义Promise库的实现细节,包括状态管理、异步处理及错误捕获机制。通过具体代码示例,展示了如何创建并测试Promise对象,以及其在JavaScript异步编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Git源码:
https://github.com/slhuang520/study/tree/master/web/es6/test/src/promise

整体结构图如下:
在这里插入图片描述

MyPromise .js

// require("babel-register"); //自动编译
// import "core-js"; //引入 polyfill
// import "regenerator-runtime/runtime";
const STATUS_PENDING = "pending";
const STATUS_RESOLVED = "resolved";
const STATUS_REJECTED = "rejected";
class MyPromise {
    constructor(fn) {
        this.catchAble = false;
        this.isRejected = false;
        this.state = STATUS_PENDING;
        this.handlers = [];
        this.frontVal;
        setTimeout(() => {
            fn(this.resolve.bind(this), this.reject.bind(this));
        });
    }

    then(resolve, reject) {
        this.handlers.push({resolve,reject});
        return this;
    }

    resolve(value){
        if (value && typeof value.then === "function") { //是否返回的是一个 Promise 对象
            value.handlers.push(...this.handlers.splice(0));
            return;
        }

        this.frontVal = value;
        if (this.state === STATUS_PENDING) {
            this.state = STATUS_RESOLVED;
        }
        this.deal();
    }

    reject(value) {
        if (value && typeof value.then === "function") {
            value.handlers.push(...this.handlers.splice(0));
            return;
        }

        this.frontVal = value;
        this.state = STATUS_REJECTED;
        this.deal();
    }

    catch(fun) {
        this.handlers.push({
            resolve: undefined,
            reject: fun
        });
        this.catchAble = true;
    }

    deal() {
        let funObj = this.findFn(),
            fn;

        if (!funObj) {
            return;
        }

        if (this.state === STATUS_RESOLVED) {
            fn = funObj.resolve;
        } else if (this.state === STATUS_REJECTED) {
            fn = funObj.reject;
        }

        if ((!fn || typeof fn !== "function") && this.state === STATUS_REJECTED) {
            if (this.catchAble) {
                this.isRejected = true;
                return this.deal();
            }
            throw new Error("Exist Un-catched Error!");
        }
        this.state = STATUS_RESOLVED;

        if (typeof fn === "function"){
            this.resolve(fn(this.frontVal)); //为何这里直接调用resolve?而不区分reject?是因为reject处理之后,后续的then还需要继续执行
        } else {
            this.resolve(fn || this.frontVal);
        }
    }

    findFn() {
        if (!this.handlers.length) {
            return;
        }

        let funObj = this.handlers.shift();
        if (this.isRejected) {
            if (typeof funObj.resolve !== "undefined") {
                return this.findFn();
            }
            this.isRejected = false;
        }
        return funObj;
    }
}

export default MyPromise;

TestMyPromise.js

import Promise from "./MyPromise.js";

class TestMyPromise {
    constructor() {

    }

    doSomeThing() {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                resolve(66);
                // reject(777);
            }, 2000);
        // });
        }).then().then(123);
    }

    test() {
        this.doSomeThing()
        .then(function (val) {
            console.log("first:", val);
            return 88;
        }, function (val) {
            console.log(val, "reject");
            return 588;
        }).then(function (val) {
            console.log("second:", val);
            return new Promise(function (resolve, reject) {
                console.log("inner promise");
                resolve(555);
            }).then().then(function (val) {
                console.log(val, "***");
                return new Promise(function (resolve, reject) {
                    console.log("inner inner promise");
                    resolve(555111);
                }).then().then(function (val) {
                    console.log(val, "111***");
                });
            });
        }).then(function (val) {
            console.log("third:", val);
        }).catch(function (e) {
            console.log("catch", e);
        });
    }
}
console.log(1);
let testPromise = new TestMyPromise();
testPromise.test();
console.log(2);

package.json

{
  "name": "test",
  "version": "1.0.0",
  "description": "npm init",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build1": "babel Promise.js -o build.js",
    "build": "babel src -d dist",
    "run-promise": "babel-node ./dist/promise/TestMyPromise.js",
    "run-iterator": "babel-node ./dist/iterator/Test.js"
  },
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.8.4",
    "@babel/core": "~7.9.0",
    "@babel/node": "~7.8.7",
    "@babel/preset-env": "^7.9.5",
    "@babel/register": "~7.9.0",
    "core-js": "^3.6.5"
  }
}

.babelrc

{
  "presets": [
    ["@babel/preset-env",
      {
        "corejs": 3,
        "useBuiltIns": "usage"
      }
    ]
  ]
}

使用 npm run build 进行编译

然后使用 npm run run-promise 执行。

运行结果如下:

1
2
first: 123
second: 88
inner promise
555 '***'
inner inner promise
555111 '111***'
third: undefined

由于使用了 import 语法,不能直接使用 node 运行。
具体原因可以参考:
SyntaxError: Unexpected token import

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值