博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自编写一套简单的Promise——myPromise
阅读量:5140 次
发布时间:2019-06-13

本文共 4779 字,大约阅读时间需要 15 分钟。

废了1-2天功夫编写了一套能实现异步Promise的构造函数,实现以下功能:

(1)通过newPromise((res,rej)=>{})构造一个Promise功能的方法

(2)通过then获取onFulfilled或者onRejected状态返回的值

(3)通过catch捕获之前rejected的错误

/*promise状态,PENDING阻塞、FULFILLED完成、REJECTED失败*/const PENDING = 0,    FULFILLED = 1,    REJECTED = 2;/*then中需要返回一个新的promise,promise初始化用的resolver*/function noop() {};/*resolver必须为一个方法,不是给出typeError提示*/function needsResolver() {    throw new TypeError('You must pass a resolver function as the first argument to the promise constructor')}/*Promise构造函数生成,不是给出typeError提示*/function needsNew() {    throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}class newPromise {    constructor(resolver) {        /*当前Promise状态*/        this.PromiseStatus = PENDING        /*final执行时需要的标记,防止乱序执行*/        this._deferredState = 0 //1在进行final  否则不在        /*存放的后续then执行的({onFulfilled,onRejected})方法*/        this._deferreds = []        /*保存当前值,可以是resolve或者reject返回的值*/        this.PromiseValue = null        /*resolver是否是方法,不是提示报错信息*/        typeof resolver !== 'function' && needsResolver();        this instanceof newPromise ? init_(this, resolver) : needsNew();    }}newPromise.prototype.then = then_newPromise.prototype.catch = catch_function init_(promise, resolver) {    try {        resolver((val) => {            resolve_(promise, val)        }, (err) => {            reject_(promise, err)        })    } catch (e) {        catch_(e)    }}/*与then相似,只是没有onFulfilled参数*/function catch_(onRejected) {    var promise = new newPromise(noop);    let handler = new Handler(this, null, onRejected, promise)    pushTo_(this, handler)    return promise;}/*reject,resolve之后会调用*/function final_(promise) {    if (promise._deferreds.length > 0) {//将结果返回        if (promise._deferredState === 1) return        promise._deferredState = 1        let defer = promise._deferreds[0]        handle_(promise, defer);    }}function pushTo_(promise, deferred) {    promise._deferreds.push(deferred)}function handle_(self, defer) {//{defer 是一个对象,有三个参数:onFulfilled,onRejected,promise    var cb = self.PromiseStatus === FULFILLED ? defer.onFulfilled : defer.onRejected;    if (cb === null) {        /*状态不变,再次调用then才将PromiseValue输出*/        self._deferreds.pop()        if (self.PromiseStatus === FULFILLED) {            resolve_(self, self.PromiseValue)        } else {            reject_(self, self.PromiseValue)        }        self._deferredState = 0    }    else if (self.PromiseStatus === PENDING) {        // if (self._deferredState === 0) {        //     self._deferredState = 1;        // }    }    else {        self._deferreds.pop()        self._deferredState = 0        let promise = self.promise        let callback = cb(self.PromiseValue)        if (callback) {            callback.then(res => {                // console.log('---', callback)                // if (callback.PromiseStatus === REJECTED)                //     reject_(promise, callback.PromiseValue)                // else                /*将callback返回值,在之前then生成的promise上发出,则promise.then可以捕获到,这样then就可以变成链式的了*/                resolve_(promise, callback.PromiseValue)            }, rej => {                reject_(promise, callback.PromiseValue)            })        }    }}//返回一个新的promisefunction then_(onFulfilled, onRejected) {    var promise = new newPromise(noop);    let handler = new Handler(this, onFulfilled, onRejected, promise)    pushTo_(this, handler)    return promise;}function resolve_(promise, val) {    promise.PromiseStatus = FULFILLED    promise.PromiseValue = val    final_(promise)}function reject_(promise, err) {    promise.PromiseStatus = REJECTED    promise.PromiseValue = err    final_(promise)}function Handler(promise, onFulfilled, onRejected, promise_) {    promise.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;    promise.onRejected = typeof onRejected === 'function' ? onRejected : null;    promise.promise = promise_;    return promise}复制代码

测试代码:

let newp = new newPromise((resolve, reject) => {    setTimeout(() => {        reject('1')    })}).then(resolve => {    console.log('resolve', resolve)}, reject => {    console.log('reject:', reject)    return new newPromise((resolve) => {        setTimeout(() => {            resolve('ok')        }, 100)    })}).then(res => {    console.log('---res---', res)    return new newPromise((resolve, reject) => {        setTimeout(() => {            reject('ok')        }, 100)    })}).then(res => {    console.log('---res2---', res)}, rej => {    console.log('---rej2---', rej)    return new newPromise((resolve, reject) => {        setTimeout(() => {            reject('err')        }, 100)    })}).catch(err => {    console.log(err)})复制代码

测试结果:

转载于:https://juejin.im/post/5d53e9b75188255db76bf89a

你可能感兴趣的文章
[HDU 2102] A计划(搜索题,典型dfs or bfs)
查看>>
推荐给4.3.3越狱用户的安全漏洞修复工
查看>>
用HTML的select+option标签实现下拉框
查看>>
[改善Java代码]asList方法产生的List对象不可更改
查看>>
ACM题目————Find them, Catch them
查看>>
LeetCode Weekly Contest 119
查看>>
Angular2-之开发环境搭建/调试环境配置
查看>>
DDA, Bresenham line's algorithm and Voxel Traversal used in the Grid-Accelerator in PBRT
查看>>
执行p4 submit后,perl文件丢了可执行属性
查看>>
数字电路中表示频率误差的ppm是什么意思?
查看>>
获取当前焦点所在元素
查看>>
11.8输入一个整数,求它是几位数
查看>>
你不知道的parseInt
查看>>
python基础之python基本数据类型
查看>>
vue中-webkit-box-orient:vertical打包放到线上不显示
查看>>
[Swift通天遁地]一、超级工具-(20)图片面部聚焦:使图像视图自动聚焦图片人物的面部位置...
查看>>
解决SVN提交和更新代码冲突?
查看>>
rem布局注意问题和meta标签
查看>>
[React Testing] Children with Shallow Rendering
查看>>
ubuntu的LAMP环境搭建
查看>>