前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >自己实现一个JavaScript Promise类

自己实现一个JavaScript Promise类

原创
作者头像
伯爵
修改于 2019-10-30 02:50:53
修改于 2019-10-30 02:50:53
6480
举报
文章被收录于专栏:前端小菜鸟前端小菜鸟

Promise对象用于表示一个异步操作的最终状态以及操作的值。Promise本质上是一个绑定了回调的对象,区别于将回调传入函数内部。

Promise 属性和方法

我们通过构造函数去创建promise实例:

let promise = new Promise( function(resolve, reject) {...} /* executor */ );

Promise构造函数传入一个参数executor函数,executor是带有resolve和reject两个参数的函数。在构造函数返回Promise实例对象前executor被调用,当前状态被初始化成pedding状态,executor内部执行一些异步操作,当异步操作执行完毕根据执行情况:当成功执行则调用resolve函数将promise状态更新为fulfilled,否则执行reject函数设置promise状态为rejected。

一个Promise只有三种状态:

  1. pedding:初始状态
  2. fulfilled:操作成功完成
  3. rejected:操作失败
Promise API

a. Promise方法

方法

描述

Promise.reject(reason)

返回一个Promise对象,状态设置为失败并传递失败原因给处理函数

Promise.resolve(value)

返回一个promise对象,能够将value以Promise是形式使用

Promise.all(iterable)

iterable 是一个数组对象,只有当iterable每个promise对象都成功执行才会触发,返回一个数组对象保存promise对象数组的执行结果,和iterable每个对象的顺序保持一致

Promise.race(iterable)

返回一个Promise,按照iterable数组任意promise对象最先执行完毕的结果立即返回,成功执行返回执行结果还是失败返回原因

b. 构造函数

构造函数

描述

new Promise( function(resolve, reject)){}

通过new关键字创建实例对象,resoleve是异步函数成功执行调用,否则执行reject

c. 原型链方法

方法

描述

promise.then(onFulfilled, onRejected)

当promise解析完成,则调用onFulfilled,如果promise拒绝,则执行onRejected,两个都是可选的参数

promise.catch

promise拒绝,等价于 promise.then(undefined, onRejected)

动手实现一个Promise类

我们已经整理了Promise对象的属性和方法,已经promise对象从原型链继承的属性和方法,现在我们需要一步一步自己去实现一个Promise类。

代码语言:txt
复制
const STATE = {
    PENDING: 'pending',
    FULFILLED: 'fulfilled',
    REJECTED: 'rejected'
}
const emptyObj = {};

function handleFun(fun, resolve, reject) {
    try {
        fun(resolve, reject);
    } catch (err) {
        reject(err);
    }
}
function getFun(fun) {
    return typeof fun === 'function' ? fun : function(e) {return e};
}

function PromiseFun(fu) {
    if(fu === emptyObj) return;
    this.defaultState = STATE.PENDING;
    this.state = STATE.PENDING;
    this.data = 0;
    this.onFulfilledList = [];
    this.onRejectedList = [];

    const resolve = (val) => {
        if(this.state !== STATE.PENDING) return;
        this.state = STATE.PENDING;
        this.data = val;
        this.onFulfilledList.forEach(fun => {
            fun(val);
        })
    }
    const reject = (reason) => {
        if(this.state !== STATE.PENDING) return;
        this.state = STATE.REJECTED;
        this.onRejectedList.forEach(fun => {
            fun(reason);
        })
    }
    handleFun(resolve, reject);
} 

PromiseFun.prototype.then = function(onFulfilled, onRejected) {
    let self = this;
    onFulfilled = getFun(onFulfilled);
    onRejected = getFun(onRejected);
    switch(this.state) {
        case STATE.PENDING:
            let fun_pending = function(resolve, rejected) {
                self.onFulfilledList.push(function(val) {
                    try {
                        let data = onFulfilled(self.data);
                        if(data instanceof PromiseFun) {
                            data.then(resolve, reject);
                        } else {
                            resolve(data);
                        }
                    } catch (err) {
                        reject(err);
                    }
                })
                self.onRejectedList.push(function(val) {
                    try {
                        let data = onRejected(self.data);
                        if(data instanceof PromiseFun) {
                            data.then(resolve, reject);
                        } else {
                            reject(data)
                        }
                    } catch (err) {
                        reject(err);
                    }
                })
            }
            return new PromiseFun(fun_pending);
        case STATE.FULFILLED:
            let fun_fulfilled = function(resolve, reject) {
                try {
                    let data = onFulfilled(self.data);
                    if(data instanceof PromiseFun) {
                        data.then(resolve, reject);
                    }else {
                        resolve(data);
                    }
                } catch (err) {
                    reject(err);
                }
            }
            return new PromiseFun(fun_fulfilled);
        case  STATE.REJECTED:
            let fun_rejected = function(resolve, reject) {
                try {
                    let data = onRejected(self.data);
                    if(data instanceof PromiseFun) {
                        data.then(resolve, reject);
                    }else {
                        reject(data);
                    }
                } catch(err) {
                    reject(err);
                }
            }  
            return new PromiseFun(fun_rejected); 
    }
}

PromiseFun.prototype.catch = function(onRejected) {
    return this.then(null, onRejected);
}

PromiseFun.resolve = function(value) {
    return new PromiseFun(function(resolve, rejected) {
        resolve(value);
    }) 
}

PromiseFun.reject = function(reason) {
    return new PromiseFun(function(resolve, rejected) {
        rejected(reason);
    })
}

PromiseFun.all = function(promiseArr) {
    if(!Array.isArray(promiseArr)) return;
    let len = promiseArr.length;
    let count = 0;
    let resultArr = [];
    for(let i = 0; i < len; i++) {
        let item = promiseArr[i];
        PromiseFun.resolve(item).then(function(val) {
            count++;
            resultArr[i] = val;
            if(count === len) {
                return reason(resultArr);
            }
        }, function(reason) {
            reject(reason)
        })
    }

}

参考

  1. 使用Promise | MDN
  2. Promise | MDN
  3. JavaScript Promise简介
  4. Promises/A+规范
  5. 剖析Promise内部结构,一步一步实现一个完整的、能通过所有Test case的Promise类
  6. promise Core.js
  7. Promise简易实现

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
Android Camera1显示预览的四种方式
相机输出的预览画面最终都会绘制到指定的Surface,然后由SurfaceFlinger进行合成并发送给显示设备
雪月清
2020/07/14
3.6K0
深入浅出Android BufferQueue
1. 背景 对业务开发来说,无法接触到BufferQueue,甚至不知道BufferQueue是什么东西。对系统来说,BufferQueue是很重要的传递数据的组件,Android显示系统依赖于BufferQueue,只要显示内容到“屏幕”(此处指抽象的屏幕,有时候还可以包含编码器),就一定需要用到BufferQueue,可以说在显示/播放器相关的领悟中,BufferQueue无处不在。即使直接调用Opengl ES来绘制,底层依然需要BufferQueue才能显示到屏幕上。 弄明白BufferQue
腾讯技术工程官方号
2019/05/16
1.9K0
深入浅出Android BufferQueue
深入浅出Android BufferQueue-下
上文主要介绍了BufferQueue的设计思想和内部实现,本文将介绍对于BufferQueue的常用封装和使用例子。
QQ音乐技术团队
2019/05/16
4.5K0
关于Camera性能优化的一些建议
上一篇文章主要介绍Camera的基本功能,我们在做相机应用的时候,除了相机的基本功能,还有一个非常重要的点,就是性能不能查,有几个方面:预览不能卡顿、拍照速度要快、录制视频不能卡。
马上就说
2022/05/25
2.6K0
关于Camera性能优化的一些建议
Android Camera 模型及 API 接口演变
要了解 Android Camear 相机模型的演变,首先还是得了解硬件抽象层 HAL 相关的知识内容。
音视频开发进阶
2019/07/26
1.5K0
Android 图形架构
要理解Android的图形架构,我们需要先理解window的概念。维基百科中给window的定义是:Window是图形用户界面(GUI)系统中显示器上一个单独的视图区域(可以想象你电脑桌面上一个个窗口)。
字节流动
2022/09/26
2.4K0
一篇文章带你了解Android 最新Camera框架
这篇文章主要分下面几点来展开讲解: 1)Android 最新Camera 整体框架; 2)Android Camera2 和HAL3 的基本了解; 3)Camera2 介绍; (本文所写的内容基于Android 9.0)
小驰行动派
2021/04/01
1.8K0
U3D激发拍照新活力,Camera360优化之旅
大家下午好,我是来自Camera360的唐雷,今天与大家一同分享Camera360 iOS端的音频优化。对于一款拍照软件,贴纸、美妆、特效现在已经成为一种标配,而我们最大的区别在于左下角的相册——它支持连拍,不需要拍照预览再去保存。从产品角度,我们最开始只是简单的拍照软件,拍风景再加上一些滤镜处理,到后面开始添加美妆、贴纸等功能,包括短视频也有尝试。
LiveVideoStack
2021/09/02
1.4K0
U3D激发拍照新活力,Camera360优化之旅
Android Camera2详解
Camera API2是Google从Android5.0开始推出的配合HAL3使用的一套新架构,相比于API1,对应用层开发者而言开放了更多的自主控制权,主要特性包括:
雪月清
2020/06/23
2.8K0
一篇文章带你了解Google CameraX
1) CameraX 是一个 Jetpack 库,最低版本是兼容到Android5.0。好学的同学们,肯定又会问,那Jetpack库又是啥呢?
小驰行动派
2022/09/22
4K0
一篇文章带你了解Google CameraX
Camera开发需要关注哪些点
我们接下来要分享VideoEditor中的相机处理模块,但是在分享之前,还是有必要将Camera的一些问题给理清楚,磨刀不误砍柴工,只有比较清晰地掌握Camera的一些特点和应用的规律,后续在优化性能和解决问题的时候就不会手忙脚乱了。
马上就说
2022/05/25
7960
Camera开发需要关注哪些点
Android Camera开发序列:Camera2 API 的简单描述和调用(预览、拍照、录像
Android 5.1 以后,添加了Camera2 的API,能够满足更多操纵camera的场景。当然,相对应camera1的调用,也变的复杂一点。
小驰行动派
2021/04/19
2K0
Android Camera SurfaceView 预览拍照
Android使用 Camera API + SurfaceView 方式进行预览拍照。
音视频开发进阶
2019/07/24
3.6K0
Android Camera2
从 Android 5.0 开始,Google 引入了一套全新的相机框架 Camera2(android.hardware.camera2)并且废弃了旧的相机框架 Camera1(android.hardware.Camera)。作为一个专门从事相机应用开发的开发者来说,这一刻我等了太久了,Camera1 那寥寥无几的 API 和极差的灵活性早已不能满足日益复杂的相机功能开发。Camera2 的出现给相机应用程序带来了巨大的变革,因为它的目的是为了给应用层提供更多的相机控制权限,从而构建出更高质量的相机应用程序。本文是 Camera2 教程的开篇作,本章将介绍以下几个内容:
ppchao
2020/12/01
2.2K0
Android Camera2
Android利用SurfaceView显示Camera图像爬坑记(二)
前一章《Android利用SurfaceView显示Camera图像爬坑记(一)》我们已经实现了利用SurfaceView将Camera中的实时帧图像显示出来了,我们做这个的主要目录是想把每一帧的数据取出后通过OpenCV图像处理后,再实时显示出处理后的图像。
Vaccae
2019/07/25
1.8K0
Android13 Camera New Feature--Mirror support
Starting from Android 13, Android supports setting Mirror for each Camera Output Stream. This article introduces the specific usage method.
雪月清
2022/09/21
8470
Android13 Camera New Feature--Mirror support
Google Jetpack 新组件 CameraX 介绍与实践
顾名思义:CameraX 就是用来进行 Camera 开发的官方库了,而且后续会有 Google 进行维护和升级。这对于广大 Camera 开发工程师和即将成为 Camera 的程序员来说,真是个好消息~~~
音视频开发进阶
2019/06/03
2K0
Google Jetpack 新组件 CameraX 介绍与实践
Android视频技术探索之旅:美团外卖商家端的实践
美美导读:移动互联网时代,4G的普及推动了移动视频的发展,丰富的视频内容满足了用户多样化的需求。美团外卖商家端也尝试引入了视频功能,旨在提升商品信息描述的丰富度。本文总结了商家端视频功能的闭环全流程实践及部分踩坑经验。
美团技术团队
2019/09/17
1.3K0
Android视频技术探索之旅:美团外卖商家端的实践
Android Camera原理之拍照流程zsl优化方案
拍照是手机的基本功能,优化拍照性能,主要是优化点击拍照到生成照片的这一段时间,看看可以在什么地方减少耗时
雪月清
2023/02/13
1.4K0
Android Camera原理之拍照流程zsl优化方案
Android平台实现Camera2数据推送到RTMP服务器
在Google 推出Android 5.0的时候, Android Camera API 版本升级到了API2(android.hardware.camera2), 之前使用的API1(android.hardware.camera)就被标为 Deprecated 了。
音视频牛哥
2021/03/02
1.3K0
相关推荐
Android Camera1显示预览的四种方式
更多 >
目录
  • Promise 属性和方法
    • Promise API
  • 动手实现一个Promise类
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档