自己写一个Promise

参考Promise 的  官方规范  https://promisesaplus.com/

Promise 其实就是一个状态机

它只有两种状态变化 pending    =》   fulfilled

         pending    =》   rejected

并且状态一旦发生变化后就不会再改变

我们用es5来实现下

先写个架子, 并测试下:

function myPromise(executor) {
    var _this = this; // 保存当前的函数上下文
    _this.status = ‘pending‘; // 初始状态
    _this.resolveValue = null;  // resolve初始值
    _this.rejectValue = null;  // reject初始值
    function resolve(value) {
        if (_this.status ==  ‘pending‘) {
            _this.status = ‘Fulfilled‘;
            _this.resolveValue = value;
        }
    }
    function reject(reason) {
        if (_this.status ==  ‘pending‘) {
            _this.status = ‘Fulfilled‘;
            _this.rejectValue = reason;
        }
    }
    try {    // 捕获错误
        executor(resolve, reject)
    } catch (e){
        reject(e);
    }
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
    var _this = this;
    if (_this.status == ‘Fulfilled‘) {
        onFulfilled(_this.resolveValue)
    }
    if (_this.status == ‘Rejected‘) {
        onRejected(_this.rejectValue)
    }
};

var p = new myPromise((resolve, reject) => {
    resolve(‘I am handsome‘);
    throw Error(‘捕获错误‘)
});
p.then((data) => {
    console.log(data)
}, (err) => {
    console.log(err)
} );

结果:

它先执行resolve   状态 变为   Fulfilled    ,

然后报错 ,执行reject , 由于此时状态不是pending, 状态还是Fulfilled

Promise的核心是处理异步,

现在我们的代码并不能等待状态的改变,

接下来我们加上处理异步操作的功能, 并测试下

function myPromise(executor) {
    var _this = this; // 保存当前的函数上下文
    _this.status = ‘pending‘; // 初始状态
    _this.resolveValue = null;  // resolve初始值
    _this.rejectValue = null;  // reject初始值
    _this.resolveCallbackList = []; // 存resolve的回调
    _this.rejectCallbackList = []; // 存reject的回调
    function resolve(value) {
        if (_this.status ==  ‘pending‘) {
            _this.status = ‘Fulfilled‘;
            _this.resolveValue = value;
            // 状态改变执行存的回调
            _this.resolveCallbackList.forEach(function(ele){
                if (ele) {
                    ele();
                }
            })
        }
    }
    function reject(reason) {
        if (_this.status ==  ‘pending‘) {
            _this.status = ‘Rejected‘;
            _this.rejectValue = reason;
            // 状态改变执行存的回调
            _this.rejectCallbackList.forEach(function(ele){
                if (ele) {
                    ele();
                }
            })
        }
    }
    try {    // 捕获错误
        executor(resolve, reject)
    } catch (e){
        reject(e);
    }
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
    var _this = this;
    if (_this.status == ‘Fulfilled‘) {
        onFulfilled(_this.resolveValue)
    }
    if (_this.status == ‘Rejected‘) {
        onRejected(_this.rejectValue)
    }
    // 等待状态时把回调存起来,状态改变再触发
    if (_this.status == ‘pending‘) {
        _this.resolveCallbackList.push(function () {
            onFulfilled(_this.resolveValue)
        });
        _this.rejectCallbackList.push(function () {
            onRejected(_this.rejectValue)
        });
    }
};

var p = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve(‘I am handsome‘);
    }, 0);
    // throw Error(‘捕获错误‘)
});
p.then((data) => {
    console.log(data)
}, (err) => {
    console.log(err)
} );

结果:

??  它已经能处理异步操作了

接下来实现链式操作, 再测试下

function myPromise(executor) {
    var _this = this; // 保存当前的函数上下文
    _this.status = ‘pending‘; // 初始状态
    _this.resolveValue = null;  // resolve初始值
    _this.rejectValue = null;  // reject初始值
    _this.resolveCallbackList = []; // 存resolve的回调
    _this.rejectCallbackList = []; // 存reject的回调
    function resolve(value) {
        if (_this.status ==  ‘pending‘) {
            _this.status = ‘Fulfilled‘;
            _this.resolveValue = value;
            // 状态改变执行存的回调
            _this.resolveCallbackList.forEach(function(ele){
                if (ele) {
                    ele();
                }
            })
        }
    }
    function reject(reason) {
        if (_this.status ==  ‘pending‘) {
            _this.status = ‘Rejected‘;
            _this.rejectValue = reason;
            // 状态改变执行存的回调
            _this.rejectCallbackList.forEach(function(ele){
                if (ele) {
                    ele();
                }
            })
        }
    }
    try {    // 捕获错误
        executor(resolve, reject)
    } catch (e){
        reject(e);
    }
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
    var _this = this;
    // 用于链式调用
    var nextPromise = new myPromise(function(res, rej) {
        if (_this.status == ‘Fulfilled‘) {
            // 存一下回调执行的结果,传给下一个.then
            var nextResolveValue = onFulfilled(_this.resolveValue);
            res(nextResolveValue);
        }
        if (_this.status == ‘Rejected‘) {
            // 存一下回调执行的结果,传给下一个.then
            var nextRejectValue = onRejected(_this.rejectValue);
            rej(nextRejectValue);
        }
        // 等待状态时把回调存起来,状态改变再触发
        if (_this.status == ‘pending‘) {
            _this.resolveCallbackList.push(function () {
                // 存一下回调执行的结果,传给下一个.then
                var nextResolveValue = onFulfilled(_this.resolveValue);
                res(nextResolveValue);
            });
            _this.rejectCallbackList.push(function () {
                var nextRejectValue = onRejected(_this.rejectValue);
                rej(nextRejectValue);
            });
        }
    });
    return nextPromise
};

var p = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve(‘I am handsome‘);
    }, 0);
    // throw Error(‘捕获错误‘)
});
p.then((data) => {
    console.log(data + ‘ suc‘ + ‘ 1‘)
    return 222
}, (err) => {
    console.log(err)
} ).then((data) => {
    console.log(data + ‘ suc‘ + ‘ 2‘)
}, (err) => {
    console.log(err)
} );

结果 :

没毛病, 可以链式调用then了  , 先不处理返回值为Promise  的 情况  ,

原生的Promise 执行方法都是异步的  , 并且执行方法是能捕捉错误,

我们加上这个功能 , 并且测试下

function myPromise(executor) {
    var _this = this; // 保存当前的函数上下文
    _this.status = ‘pending‘; // 初始状态
    _this.resolveValue = null;  // resolve初始值
    _this.rejectValue = null;  // reject初始值
    _this.resolveCallbackList = []; // 存resolve的回调
    _this.rejectCallbackList = []; // 存reject的回调
    function resolve(value) {
        if (_this.status ==  ‘pending‘) {
            _this.status = ‘Fulfilled‘;
            _this.resolveValue = value;
            // 状态改变执行存的回调
            _this.resolveCallbackList.forEach(function(ele){
                if (ele) {
                    ele();
                }
            })
        }
    }
    function reject(reason) {
        if (_this.status ==  ‘pending‘) {
            _this.status = ‘Rejected‘;
            _this.rejectValue = reason;
            // 状态改变执行存的回调
            _this.rejectCallbackList.forEach(function(ele){
                if (ele) {
                    ele();
                }
            })
        }
    }
    try {    // 捕获错误
        executor(resolve, reject)
    } catch (e){
        reject(e);
    }
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
    var _this = this;
    // 用于链式调用
    var nextPromise = new myPromise(function(res, rej) {
        if (_this.status == ‘Fulfilled‘) {
            // 存一下回调执行的结果,传给下一个.then
            setTimeout(function () {
                // 捕获错误
                try {
                    var nextResolveValue = onFulfilled(_this.resolveValue);
                    res(nextResolveValue);
                } catch (e) {
                    rej(e)
                }

            },0)
        }
        if (_this.status == ‘Rejected‘) {
            // 存一下回调执行的结果,传给下一个.then
            setTimeout(function () {
                // 捕获错误
                try {
                    var nextRejectValue = onRejected(_this.rejectValue);
                    rej(nextRejectValue);
                } catch (e) {
                    rej(e)
                }
            },0)
        }
        // 等待状态时把回调存起来,状态改变再触发
        if (_this.status == ‘pending‘) {
            _this.resolveCallbackList.push(function () {
                // 存一下回调执行的结果,传给下一个.then
                setTimeout(function () {
                    // 捕获错误
                    try {
                        var nextResolveValue = onFulfilled(_this.resolveValue);
                        res(nextResolveValue);
                    } catch (e) {
                        rej(e)
                    }
                },0)
            });
            _this.rejectCallbackList.push(function () {
                setTimeout(function () {
                    // 捕获错误
                    try {
                        var nextRejectValue = onRejected(_this.rejectValue);
                        rej(nextRejectValue);
                    } catch (e) {
                        rej(e)
                    }
                },0)
            });
        }
    });
    return nextPromise
};

var p = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve(‘I am handsome‘);
        console.log(111)
    }, 0);
    // throw Error(‘捕获错误‘)
});
p.then((data) => {
    console.log(data + ‘ suc‘ + ‘ 1‘);
    throw Error(‘bao cuo‘)
}, (err) => {
    console.log(err + ‘ err‘ + ‘ 1‘)
} ).then((data) => {
    console.log(data + ‘ suc‘ + ‘ 2‘)
}, (err) => {
    console.log(err + ‘ err‘ + ‘ 2‘)
} );
console.log(222);

预期结果  222  =》 111 =》 I am handsome suc 1    =》   Error: bao cuo err 2

实际结果:

没毛病, 异步并且捕获到错误了

我们再来处理 空 then()    就是then里面不传参数的情况, 并测试

myPromise.prototype.then = function (onFulfilled, onRejected) {
    // 参数为空把值直接传给下一个then
    if (!onFulfilled) {
        onFulfilled = function (val) {
            return val;
        }
    }
    if (!onRejected) {
        onRejected = function (val) {
            return new Error(val)
        }
    }
    var _this = this;
    // 用于链式调用
    var nextPromise = new myPromise(function(res, rej) {
        if (_this.status == ‘Fulfilled‘) {
            // 存一下回调执行的结果,传给下一个.then
            setTimeout(function () {
                // 捕获错误
                try {
                    var nextResolveValue = onFulfilled(_this.resolveValue);
                    res(nextResolveValue);
                } catch (e) {
                    rej(e)
                }

            },0)
        }
        if (_this.status == ‘Rejected‘) {
            // 存一下回调执行的结果,传给下一个.then
            setTimeout(function () {
                // 捕获错误
                try {
                    var nextRejectValue = onRejected(_this.rejectValue);
                    rej(nextRejectValue);
                } catch (e) {
                    rej(e)
                }
            },0)
        }
        // 等待状态时把回调存起来,状态改变再触发
        if (_this.status == ‘pending‘) {
            _this.resolveCallbackList.push(function () {
                // 存一下回调执行的结果,传给下一个.then
                setTimeout(function () {
                    // 捕获错误
                    try {
                        var nextResolveValue = onFulfilled(_this.resolveValue);
                        res(nextResolveValue);
                    } catch (e) {
                        rej(e)
                    }
                },0)
            });
            _this.rejectCallbackList.push(function () {
                setTimeout(function () {
                    // 捕获错误
                    try {
                        var nextRejectValue = onRejected(_this.rejectValue);
                        rej(nextRejectValue);
                    } catch (e) {
                        rej(e)
                    }
                },0)
            });
        }
    });
    return nextPromise
};

var p = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve(‘I am handsome‘);
    }, 0);
    // throw Error(‘捕获错误‘)
});
p.then((data) => {
    console.log(data + ‘ suc‘ + ‘ 1‘);
    throw Error(‘bao cuo‘)
}, (err) => {
    console.log(err + ‘ err‘ + ‘ 1‘)
} ).then( ).then((data) => {
    console.log(data + ‘ suc‘ + ‘ 3‘)
}, (err) => {
    console.log(err + ‘ err‘ + ‘ 3‘)
} );

结果:

??  第一个then里抛出的错误被第三个then 接受到了, 没毛病

接下来处理 返回值为promise的情况, 并测试

如果返回值为promise,后面的then就取决于返回的promise的状态

// 处理返回值的函数
function ResolutionRetrunPromise (nextPromise, returnValue, res, rej) {
    // 返回值是否是promise
    if (returnValue instanceof  myPromise) {
        returnValue.then(function (val) {
            res(val)
        },function (reason) {
            rej(reason)
        })
    } else {
        res(returnValue)
    }
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
    // 参数为空把值直接传给下一个then
    if (!onFulfilled) {
        onFulfilled = function (val) {
            return val;
        }
    }
    if (!onRejected) {
        onRejected = function (reason) {
            return new Error(reason)
        }
    }
    var _this = this;
    // 用于链式调用
    var nextPromise = new myPromise(function(res, rej) {
        if (_this.status == ‘Fulfilled‘) {
            // 存一下回调执行的结果,传给下一个.then
            setTimeout(function () {
                // 捕获错误
                try {
                    var nextResolveValue = onFulfilled(_this.resolveValue);
                    // 处理返回值
                    ResolutionRetrunPromise(nextPromise, nextResolveValue, res, rej)
                    // res(nextResolveValue);
                } catch (e) {
                    rej(e)
                }

            },0)
        }
        if (_this.status == ‘Rejected‘) {
            // 存一下回调执行的结果,传给下一个.then
            setTimeout(function () {
                // 捕获错误
                try {
                    var nextRejectValue = onRejected(_this.rejectValue);
                    ResolutionRetrunPromise(nextPromise, nextRejectValue, res, rej)
                    // rej(nextRejectValue);
                } catch (e) {
                    rej(e)
                }
            },0)
        }
        // 等待状态时把回调存起来,状态改变再触发
        if (_this.status == ‘pending‘) {
            _this.resolveCallbackList.push(function () {
                // 存一下回调执行的结果,传给下一个.then
                setTimeout(function () {
                    // 捕获错误
                    try {
                        var nextResolveValue = onFulfilled(_this.resolveValue);
                        ResolutionRetrunPromise(nextPromise, nextResolveValue, res, rej)
                        // res(nextResolveValue);
                    } catch (e) {
                        rej(e)
                    }
                },0)
            });
            _this.rejectCallbackList.push(function () {
                setTimeout(function () {
                    // 捕获错误
                    try {
                        var nextRejectValue = onRejected(_this.rejectValue);
                        ResolutionRetrunPromise(nextPromise, nextRejectValue, res, rej)
                        // rej(nextRejectValue);
                    } catch (e) {
                        rej(e)
                    }
                },0)
            });
        }
    });
    return nextPromise
};

var p = new myPromise((resolve, reject) => {
    setTimeout(() => {
        resolve(‘I am handsome‘);
    }, 1000);
});
p.then((data) => {
    console.log(data + ‘ suc‘ + ‘ 1‘);
    return new myPromise((resolve, reject) => {
        reject(‘promise‘)
    })
}, (err) => {
    console.log(err + ‘ err‘ + ‘ 1‘)
} ).then((data) => {
    console.log(data + ‘ suc‘ + ‘ 3‘)
}, (err) => {
    console.log(err + ‘ err‘ + ‘ 3‘)
} );

结果:

到此 Promise 的 基本功能就实现了  ,

感兴趣的同学可以基于此 自己实现一下Promise 的   静态方法 。 。 。 。。 。

原文地址:https://www.cnblogs.com/LHLVS/p/10796751.html

时间: 2024-10-29 21:42:37

自己写一个Promise的相关文章

手写一个promise

Promise A+ 规范:https://promisesaplus.com/ 代码实现 class myPromise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolvedArray = []; this.onRejectedArray = []; const resolve = (val) => { if (this

深入理解Promise并写一个符合Promise a+规范的Promise代码

关于Promise函数可以参考我写的这篇文章https://www.cnblogs.com/qiaohong/p/7705262.html,我们现在就深入理解一下这个函数. 首先说下Promise方法,Promise方法中还是有些是比较好用的,比如说Promise.all()方法(Promise.all()方法的参数是一个数组,会按照数组的结果放到成功的回调里,如果有一个错误那么就不会成功).Promise.race()方法(这个方法的参数也是一个数组,Promise.race()会同时发起并发

如果一个promise永不resolve,会内存泄漏吗

答:跟内存泄漏没有直接关系gc的策略不会改变,如果该promise没有被人引用,就会被gc掉.如果仍被引用,就不会被gc掉.即使一个promise,resolve或者reject了,但是它还被人引用,仍然占用内存. 李政 2015/11/19 16:28:39嗯差不多,可以认为promise就是一个普通的对象,不过在vm底层会由host提供一些机制来托管promise.比如chrome的调试器里可以看到所有的promise李政 2015/11/19 16:28:56比如node里面通过nextT

操刀 requirejs,自己动手写一个

前沿 写在文章的最前面 这篇文章讲的是,我怎么去写一个 requirejs . 去 github 上fork一下,顺便star~ requirejs,众所周知,是一个非常出名的js模块化工具,可以让你使用模块化的方式组织代码,并异步加载你所需要的部分.balabala 等等好处不计其数. 之所以写这篇文章,是做一个总结.目前打算动一动,换一份工作.感谢 一线码农 大大帮忙推了携程,得到了面试的机会. 面试的时候,聊着聊着感觉问题都问在了自己的“点”上,应答都挺顺利,于是就慢慢膨胀了.在说到模块化

手写基于Promise A+规范的Promise

const PENDING = 'pending';//初始态const FULFILLED = 'fulfilled';//初始态const REJECTED = 'rejected';//初始态function Promise(executor){ let self = this;//先缓存当前promise实例 self.status = PENDING;//设置状态 //定义存放成功的回调的数组 self.onResolvedCallbacks = []; //定义存放失败回调的数组 s

js手写一个实现一个简单的promise__小前端chenMr

1.首先来看一下promise常用场景 function chenPromise (arg) { return new Promise (resolve, reject) { if () { doSomeThing(arg) resolve(val) } else { reject(val) } } }chenPromise(arg).then(((val) => {}, (err) =>{}) 2.了解promise状态 1.常规分三种:PENDING, RESOLVED, REJECTED

请写一个算法,用于将list集合内重复元素剔除

package Homework; import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Scanner;/** * list集合是否可以包含重复元素? * 如果可以,请写一个算法,用于将list集合内重复元素剔除. * @author 张致远 * */public class Homework2 { public static void main(String[]

用java写一个远程视频监控系统,实时监控(类似直播)我想用RPT协议,不知道怎么把RPT协议集成到项目中

我最近在用java写一个远程视频监控系统,实时监控(类似直播)我想用RPT协议,不知道怎么把RPT协议集成到项目中,第一次写项目,写过这类项目的多多提意见,哪方面的意见都行,有代码或者demo的求赏给我,谢谢

c语言:写一个函数建立一个有3名学生数据的单向动态链表

写一个函数建立一个有3名学生数据的单向动态链表. 解:程序: #include<stdio.h> #include<stdlib.h> #define LEN sizeof(struct Student) struct Student { long num; float score; struct Student *next; }; int n; struct Student *creat(void)//定义函数返回一个指向链表头的指针 { struct Student *head