0

0

Promise实现思路的深入分析(代码示例)

不言

不言

发布时间:2018-11-24 14:09:22

|

2070人浏览过

|

来源于segmentfault

转载

本篇文章给大家带来的内容是关于promise实现思路的深入分析(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

Promise实现思路的个人理解

我一直觉得Promise虽然方便,但是它的写法很怪,无法理解实现Promise的人是如何思考的。

不过最近我对于实现Promise的思考过程的有了一点点个人理解,特此记下。

感觉这篇文章我还是没有把思路说清楚,时间紧张,就当做一次记录,回头我要把这个过程在表达的在清楚一点。

用例

   var p1 = new Promise2( ( resolve, reject ) => {
            setTimeout( () => {
                resolve( 'hello' )
            }, 1000 )

        } )

        p1.then( res => {
                console.log( res + 'world' )
                return res + 'world'
            } )
            .then( res => {
                console.log( res + 'ziwei' )
                return res + 'ziwei'
            } )

我觉得实现一个函数跟封装组件类似,首先从以下几点考虑:

  • 1.这个函数用来做什么的?

  • 2.接受哪些参数

  • 3.返回值是什么

那么结合例子,和这几个问题,我们得到

  • 1.Promise是做异步流程控制的。通俗说就是,我希望某个函数暂时不执行,等我希望它执行时,就resolve一下,你这个函数在执行。

  • 2.构造函数Promise接受一个函数。函数的参数是resolve,reject,resolve和reject也是函数,是给用户调用用的,当用户希望下一个异步执行时,就调用resolve(0

  • 3.返回一个promise实例。 promise实例都有一个then方法,而then方法也返回一个新的promise实例。由此就可以链式调用then了

先实现一个Promise(未实现then的链式调用)
  • 1.Promise接受一个fn,不管其他,你觉得这个fn在内部会干嘛?只能被调用呗,所以虽然不知道怎么搞,但是先调用一下fn(resolve,reject)

  • 2.那这个resolve和reject不是用户实现的,所以肯定是Promise开发者实现的,那我们要实现resolve和reject,它们是干嘛的,肯定用来是改变状态的,所以定义this.state

  • 3.resolve和reject也会接受用户的参数吧,那我们就需要把这个参数用this.value缓存一下,将来then方法调用时,需要传递进去

    HaloTool
    HaloTool

    AI工具在线集合网站

    下载
  • 4.then接受successFn和errorFn,这2个就是我们希望暂时不执行的函数了。怎么做到暂时不执行呢?就是声明2个数组,把他们先存起来,将来resolve时,在调用

        class Promise2 {
            constructor( fn ) {
                this.successFnArray = []  // 用来缓存successFn和errorFn
                this.errorFnArray = []
                this.state = 'pendding'
                const resolve = ( res ) => {      // resolve就做2件事情  1: 修改状态 2:调用successFn
                    this.state = 'fulfilled'
                    this.value = res         // this.value用来缓存data数据或者error

                    this.successFnArray.forEach( successFn => {
                        successFn( res )
                    } )
                }
                const reject = ( err ) => {
                    this.state = 'rejected'
                    this.value = err

                    this.errorFnArray.forEach( errorFn => {
                        errorFn( res )
                    } )
                }
                fn( resolve, reject )   // 先调用fn再说
            }

            then( successFn, errorFn ) {
                switch ( this.state ) {
                    case 'fulfilled':
                        successFn( this.value )        // 如果调用了resolve,状态就成了fulfilled,就会执行successFn
                        break
                    case 'rejected':
                        errorFn( this.value )
                        break
                    case 'pendding':
                        this.successFnArray.push( successFn )   // 如果还没调用resolve,状态就是pendding,就先把这些异步函数缓存起来。将来resole时调用
                        this.errorFnArray.push( errorFn )
                }
            }
        }

        var p1 = new Promise2( ( resolve, reject ) => {
            setTimeout( () => {
                resolve( 'hello' )
            }, 1000 )

        } )

        p1.then( res => {
            console.log( res + 'world' )
            return res + 'world'
        } )

实现then链式调用

then的实现,和JQ的链式调用不同,JQ是每次调用方法后,把this返回

而Promise规范要求,每次都要返回新的Promise对象

所以只需要把then方法修改一下。

这部分可能会迷惑,但是我想先说一下这里做了哪些事情,其实变化不大

之前的then做了哪些事情?

  • 就是按照不同的state,调用了successFn或者errorFn,如果是pendding状态就先缓存起来,等将来resolve时调用

链式then有哪些改动?

  • 首先then有了返回值,返回一个promise,而之前没有返回值,return的是undefined

  • new Promise的过程,其实逻辑没什么变化,唯一注意的,比如状态fulfilled时,并非直接调用successFn

而是调用_successFn,而这个函数内部本质上还是调用successFn(),但同时把调用的返回值作为了resolve的参数,调用了resolve()

因为当successFn被调用,得到返回值时,就表示这个函数执行完了,

就需要执行下一个异步函数了,这样下一个异步函数也会把successFn(res)的return值作为参数

       then( successFn, errorFn ) {
                
                return new Promise2( ( resolve, reject ) => {
                    const _successFn = res => {
                        resolve(successFn(res))
                    }
                    const _errorFn = err => {
                        reject(errorFn(err))
                    }
                    
                    switch ( this.state ) {
                        case 'fulfilled':
                        _successFn( this.value )
                            break
                        case 'rejected':
                        _errorFn( this.value )
                            break
                        case 'pendding':
                            this.successFnArray.push( _successFn )
                            this.errorFnArray.push( _errorFn )
                    }
                } )

            }

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
promise的用法
promise的用法

“promise” 是一种用于处理异步操作的编程概念,它可以用来表示一个异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise的用法主要包括构造函数、实例方法(then、catch、finally)和状态转换。

339

2023.10.12

html文本框类型介绍
html文本框类型介绍

html文本框类型有单行文本框、密码文本框、数字文本框、日期文本框、时间文本框、文件上传文本框、多行文本框等等。详细介绍:1、单行文本框是最常见的文本框类型,用于接受单行文本输入,用户可以在文本框中输入任意文本,例如用户名、密码、电子邮件地址等;2、密码文本框用于接受密码输入,用户在输入密码时,文本框中的内容会被隐藏,以保护用户的隐私;3、数字文本框等等。

429

2023.10.12

Python WebSocket实时通信与异步服务开发实践
Python WebSocket实时通信与异步服务开发实践

本专题聚焦 Python 在实时通信场景中的开发实践,系统讲解 WebSocket 协议原理、长连接管理、消息推送机制以及异步服务架构设计。内容包括客户端与服务端通信实现、连接稳定性优化、消息队列集成及高并发处理策略。通过完整案例,帮助开发者构建高效稳定的实时通信系统,适用于聊天应用、实时数据推送等场景。

2

2026.03.18

Java Spring Security权限控制与认证机制实战
Java Spring Security权限控制与认证机制实战

本专题围绕 Java 后端安全体系建设展开,重点讲解 Spring Security 在权限控制与认证机制中的应用实践。内容涵盖用户认证流程、权限模型设计、JWT 鉴权方案、OAuth2 集成以及接口安全防护策略。通过实际项目案例,帮助开发者构建安全可靠的后端认证体系,提升系统安全性与可扩展能力。

0

2026.03.18

抖漫入口地址合集
抖漫入口地址合集

本专题整合了抖漫入口地址相关合集,阅读专题下面的文章了解更多详细地址。

110

2026.03.17

多环境下的 Nginx 安装、结构与运维实战
多环境下的 Nginx 安装、结构与运维实战

本专题聚焦多环境下Nginx实战,详解开发、测试及生产环境的差异化安装策略与目录结构规划。深入剖析配置模块化设计、灰度发布流程及跨环境同步机制。结合监控告警、故障排查与自动化运维工具,提供全链路管理方案,助力团队构建灵活、高可用的Nginx服务体系,从容应对复杂业务场景挑战。

13

2026.03.17

PS 批量添加图片
PS 批量添加图片

本专题整合了PS批量添加图片教程合集,阅读专题下面的文章了解更多详细操作。

10

2026.03.17

Nginx 基础架构:从安装配置到系统化管理
Nginx 基础架构:从安装配置到系统化管理

本专题深入解析Nginx基础架构,涵盖从源码编译与包管理安装,到核心配置文件优化及虚拟主机部署。进一步探讨日志轮转、性能调优、高可用集群构建及自动化运维策略,助力管理员实现从单一服务搭建到企业级系统化管理的全面升级,确保Web服务高效、稳定运行。

7

2026.03.17

mulerun骡子快跑入口地址汇总
mulerun骡子快跑入口地址汇总

本专题整合了mulerun入口地址合集,阅读专题下面的文章了解更多详细内容。

216

2026.03.17

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6.2万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号