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

自己实现一个JavaScript Promise类

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

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
AI代码解释
复制
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 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Promise实现原理
我们工作中免不了运用promise用来解决异步回调问题。平时用的很多库或者插件都运用了promise 例如axios、fetch等等。但是你知道promise是咋写出来的呢?
OECOM
2020/07/01
1.1K0
从零开始实现一个Promise
众所周知,Promise是ES6引入的新特性,旨在解决回调地狱。下面是一个简单的例子:控制接口调用顺序:
helloworld1024
2022/10/14
1800
手写Promise完整介绍
Promise是一种用于处理异步操作的机制,它可以将异步操作的结果以同步的方式进行处理和返回。在JavaScript中,Promise是一种内置对象,但我们也可以手动实现一个Promise类来更好地理解其原理和工作方式。
can4hou6joeng4
2023/11/16
4520
实现一个 Promises/A+
完整高频题库仓库地址:https://github.com/hzfe/awesome-interview
HZFEStudio
2021/09/16
3640
一次就想搞懂这个Promise
看了好多例子,调试了很久,结果和内置promise还是存在一点差异,不尽相同。 // 重点是then的参数两个参数是函数,而这两个函数的返回值,可能是一个Promise对象,或一个普通对象或一个有then方法的对象或者是个基础数据类型 class Promise { static PENDING = 'pending' static FULFILLED = 'fulfilled' static REJECTED = 'rejected'
刘嘿哈
2022/10/25
6330
深入理解 Promise 之手把手教你写一版
什么是 Promise? 语法上:Promise 是一个构造函数,返回一个带有状态的对象 功能上:Promise 用于解决异步函数并根据结果做出不同的应对 规范上:Promise 是一个拥有 then 方法的对象(在 JS 里函数也是对象) 为什么要用 Promise? 前端最令人头疼的事情之一就是处理异步请求: function load() { $.ajax({ url: 'xxx.com', data: 'jsonp', success: fun
用户1097444
2022/06/29
5310
深入理解 Promise 之手把手教你写一版
手写系列-这一次,彻底搞懂 Promise
想要实现 Promise,必须先了解 Promise 是什么,以及 Promise 有哪些功能。
游魂
2023/10/17
2690
手写系列-这一次,彻底搞懂 Promise
「一次写过瘾」手写Promise全家桶+Generator+async/await
Promise 的三个状态分别是 pending、fulfilled 和 rejected。
童欧巴
2020/12/31
9730
「一次写过瘾」手写Promise全家桶+Generator+async/await
前端一面高频面试题(附答案)
我们常说的代理也就是指正向代理,正向代理的过程,它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求。
loveX001
2022/12/14
5910
实现一个promise之完成对x的处理并测试
完成之后,promise官方推荐了一个测试方法,只有通过测试才算符合标准的promise:
wade
2020/04/23
6400
实现一个promise之完成对x的处理并测试
实现Promise的原型方法--前端面试能力提升
静态方法:resolve、reject、race、all、allSettled、any
helloworld1024
2022/09/30
6570
JavaScript中的Promise
Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象
刘亦枫
2020/03/19
1.2K0
前端异步技术之Promise
由于是参(抄)考(袭)前辈的polyfill,自己编码测试时出现了两处错误,ES6 Promise 规范的2.3.1和2.3.4
Jack Chen
2019/03/06
5090
从0到1实现Promise
Promise大家一定都不陌生了,JavaScript异步流程从最初的Callback,到Promise,到Generator,再到目前使用最多的Async/Await(如果对于这些不熟悉的可以参考我另一篇文章《JavaScript异步编程》),这不仅仅是技术实现的发展,更是思想上对于如何控制异步的递进。Promise作为后续方案的基础,是重中之重,也是面试时候最常被问到的。
leocoder
2022/04/08
9541
从0到1实现Promise
Javascript之我也来手写一下Promise
  Promise太重要了,可以说是改变了JavaScript开发体验重要内容之一。而Promise也可以说是现代Javascript中极为重要的核心概念,所以理解Promise/A+规范,理解Promise的实现,手写Promise就显得格外重要。如果要聊Promise就要从回调函数聊到回调地狱,再聊到同步异步,最终聊到Promise、async await。但是我们这篇文章,目的是手写Promise,这些前置知识如果大家不了解的话,希望可以去补充一下。那你可能会说了,我他妈不懂你在说啥,我就是想手写Promise,不行么?大佬~~那肯定是没问题的。好了,废话不多说,咱们开始吧。
zaking
2022/09/09
8430
从0到1实现Promise前言正文结束
Promise大家一定都不陌生了,JavaScript异步流程从最初的Callback,到Promise,到Generator,再到目前使用最多的Async/Await(如果对于这些不熟悉的可以参考我另一篇文章《JavaScript异步编程》),这不仅仅是技术实现的发展,更是思想上对于如何控制异步的递进。Promise作为后续方案的基础,是重中之重,也是面试时候最常被问到的。
leocoder
2018/10/31
1K0
京东前端高频面试题合集
现代计算机中数据都是以二进制的形式存储的,即0、1两种状态,计算机对二进制数据进行的运算加减乘除等都是叫位运算,即将符号位共同参与运算的运算。
yyzzabc123
2022/09/13
5210
按照 Promise/A+ 手写Promise,通过promises-aplus-tests的全部872个测试用例
链接:https://juejin.cn/post/6910500073314975758
落落落洛克
2021/01/07
9600
JS:你真的会用 Promise 吗?
试想一下,有 3 个异步请求,第二个需要依赖第一个请求的返回结果,第三个需要依赖第二个请求的返回结果,一般怎么做?
WEBJ2EE
2019/07/19
2.7K0
JS:你真的会用 Promise 吗?
前端二面手写面试题总结
then 方法返回一个新的 promise 实例,为了在 promise 状态发生变化时(resolve / reject 被调用时)再执行 then 里的函数,我们使用一个 callbacks 数组先把传给then的函数暂存起来,等状态改变时再调用。
helloworld1024
2022/10/27
8260
相关推荐
Promise实现原理
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文