Promise 的简单实现

本文通过实现一个简单的自定义Promise,帮助理解Promise的工作原理。包括状态管理、链式调用及错误处理。

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

前言

在上一篇文章 Promise 学习中了解了 Promise 的使用场景和使用方法,
这篇文章是考虑如何自己实现一个简单 Promise,用以理解 Promise

需求

实现如下要求:

doSomething().then(function(res){ // resdoSomething() 的结果
    doSomethingElse(res);
});

Promise 写法

使用原生 Promise 方法,代码会如下:

function doSomething() {
    var result = 1;
    return new Promise(function (resolve) {
        resolve(result);
    });
}
function doSomethingElse(arg) {
    console.log(arg);
}
doSomething().then(function (res) {
    doSomethingElse(res);  // 输出 1,然后返回结果是一个 Promise 对象,可以继续链式调用 then 方法
});

仿Promise 写法

接下来仿制一下这个 Promise 函数:
FPromise 是有状态的(Pending、Fulfilled、Rejected)

function FPromise(fn) {
    var status = "Pending"; // 初始状态
    var res = null;

    function handleFulfilled(value) {
        status = "Fulfilled";
        res = value;
    }

    function handleRejected(reason) {
        status = "Rejected";
        res = reason;
    }

    function handle(handler) {
        var callback = null;
        if (status == "Fulfilled") {
            callback = handler.onFulfilled;
        } else if (status == "Rejected") {
            callback = handler.onRejected;
        }

        callback(res);
    }

    this.then = function (onFulfilled, onRejected) {
        handle({
            onFulfilled: onFulfilled,
            onRejected: onRejected
        })

    }

    fn(handleFulfilled, handleRejected);
}

和原生 Promise 的调用方法一样,把 Promise 换成 FPromise 如下:

function doSomething() {
    var result = 1;
    return new FPromise(function (resolve) { // 和 Promise 一样调用
        resolve(result);
    });
}
function doSomethingElse(arg) {
    console.log(arg);
}
doSomething().then(function (res) {
    doSomethingElse(res); // 输出 1,但是没有返回结果,无法继续链式调用 then 方法
});

使用 reject 的情况如下:

function doSomething() {
    var result = 2;
    return new FPromise(function (resolve, reject) {
        if (result == 1) {
            resolve(result);
        } else {
            reject("error");
        }
    });
}
doSomething().then(null, function (reason) {
    console.log(reason) // 输出 ‘error’
});

上面的 FPromise 函数无法进行链式调用,需要在 then 方法中再返回一个新的 FPromise,继续修改之

function FPromise(fn) {
    var status = "Pending"; // 初始状态
    var res = null;

    function handleFulfilled(value) {
        status = "Fulfilled";
        res = value;
    }

    function handleRejected(reason) {
        status = "Rejected";
        res = reason;
    }

    function handle(handler) {

        var callback = null;
        if (status == "Fulfilled") {
            callback = handler.onFulfilled;
        } else if (status == "Rejected") {
            callback = handler.onRejected;
        }


        if (callback) {
            var tmp = callback(res);
            if (status == "Fulfilled") { 
                handler.resolve && handler.resolve(tmp); // 第二个 FPromise 里面的参数是第一个 FPromise 执行的结果
            } else if (status == "Rejected") {
                handler.reject && handler.reject(tmp);
            }
        }
    }

    this.then = function (onFulfilled, onRejected) {
        return new FPromise(function (resolve, reject) {
            handle({
                onFulfilled: onFulfilled,
                onRejected: onRejected,
                resolve: resolve, // 相当于下一个promise 的onFulfilled 方法
                reject: reject
            })
        });
    }

    fn(handleFulfilled, handleRejected);
}

链式调用 then 方法如下,

function doSomething() {
    var result = 1;
    return new FPromise(function (resolve) {
        resolve(result);
    });
}
function doSomethingElse(arg) {
    console.log(arg);
}
doSomething().then(function (res) {
    doSomethingElse(res); // 输出 1
    return res;
}).then(function (res) {
    console.log(res + 1); // 输出 2
});

总结

本文实现的方法只能用于参考 Promise 的原理,还有很多特性没有实现,比如 race,all 方法的实现。一个更好的实现参考https://github.com/LucaslEliane/fake-promise/blob/master/fake-promise.jsMDN 文档中推荐的是 Promise-Polyfill

如何更好的使用 Promise 可以参考这个文章https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值