promise原理:代码实现

2023-11-04

基础代码

(function (window) {
    const PENDING = 'pending'
    const RESOLVED = 'resolved'
    const REJECTED = 'rejected'

    function Promise(excutor) {
        this._state = PENDING
        this._value = undefined
        this._callbacks = [];

        let _this = this;
        function resolve(value) {
            //这里面不能直接使用用this,因为不是在内部调用的,会改变this的指向
            if (_this.state !== PENDING) return ///多个resolved调用,保持仅有一个resolved函数有效
            _this._state = RESOLVED
            _this._value = value
            if (_this._callbacks.length) {
                setTimeout(_ => {
                    _this._callbacks.forEach(callback => {
                        callback.onResolved(value)
                    })
                }, 0)
            }
        }

        function reject(reason) {
            if (_this.state !== PENDING) return //多个reject调用,保持仅有一个reject函数有效
            _this._state = REJECTED
            if (_this._callbacks.length) {
                setTimeout(_ => {
                    _this._callbacks.forEach(callback => {
                        callback.onRejected(value)
                    })
                }, 0)
            }
        }
        try {
            excutor(resolve, reject)
        } catch (err) {
            reject(err);
        }
    }

    /**
     * 
     * @param {*} onResolved 
     * @param {*} onRejected 
     * 返回的promise的结果由 onResolved/onRejected 的执行结果决定
     */
    Promise.prototype.then = function (onResolved, onRejected) {
        //透传处理
        onResolved = typeof onResolved === 'function' ? onResolved : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

        let _this = this;

        return new Promise((resolve, reject) => {
            function handle(callback) {
                try {
                    let result = callback(_this.value)
                    if (result instanceof Promise) {
                        result.then(resolve, reject)
                    } else {
                        resolve(result)
                    }
                } catch (err) {
                    reject(err)
                }
            }
            //处理三种状态PENDING/RESOLVED/REJECTED
            if (_this._state === PENDING) {
                _this._callbacks.push({
                    onResolved() {
                        handle(onResolved)
                    },
                    onRejected() {
                        handle(onRejected)
                    }
                })
            } else if (_this._state === RESOLVED) {
                //1.返回的是promise, resolve,reject
                //2.返回的是非promise
                //3.处理异常

                //立即异步执行
                setTimeout(_ => {
                    handle(onResolved)
                })
            } else {
                handle(onRejected)
            }
        })
    }
    Promise.prototype.catch = function (onRejected) {
        return this.then(undefined, onRejected)
    }
  
})(window)

静态方法

Promise.resolve/Promiss.reject

//返回一个失败状态的promise
Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason)
    })
}

Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then(resolve, reject)
        } else {
            resolve(value)
        }
    })
}

Promise.all的逻辑实现


/**
 * 
 * @param {*} promises promise的数组
 */
Promise.all = function (promises) {
    let values = new Array(promises.length);
    let resolveCount = 0;
    return new Promise((resolve, reject) => {
        promises.forEach((p, index) => {
            //Promise.resolve(p):把p统一处理成promise
            Promise.resolve(p).then(value => {
                resolveCount++;//成功的计数
                values[index] = value
                if (resolveCount === promises.length) {
                    resolve(values)
                }
            }, reason => {//有一个失败就整体失败
                reject(reason)
            })
        })
    })
}

Promise.race 的整体实现

Promise.race = function (promises) {
        return new Promise((resolve, reject) => {
            promises.forEach(p => {
                //Promise.resolve(p):把p统一处理成promise
                Promise.resolve(p).then(value => {
                    resolve(value)//有一个成功就整体失败
                }, reason => {//有一个失败就整体失败
                    reject(reason)
                })
            })
        })
    }

Promise.resolveDelay/Promoise.rejectDelay

Promise.resolveDelay = function (value, timeout) {
        return new Promise((resolve, reject) => {
            setTimeout(_ => {
                if (value instanceof Promise) {
                    value.then(resolve, reject)
                } else {
                    resolve(value)
                }
            }, timeout)
        })
    }

Promise.rejectDelay = function (reason, timeout) {
    return new Promise((resolve, reject) => {
        setTimeout(_ => {
            reject(reason)ð
        }, timeout)
    })
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

promise原理:代码实现 的相关文章

  • javascript/jquery 从选择中删除或删除选项

    在某些情况下 我需要从选择中删除选项 基本上 if mystatement true remove item with id option1 from select of id select1 有人知道我可以实现这一目标的代码吗 非常感谢
  • 声明为对象文字与函数的剔除视图模型之间的区别

    在knockout js中 我看到视图模型声明为 var viewModel firstname ko observable Bob ko applyBindings viewModel or var viewModel function
  • 如何打开新选项卡并更改当前页面

  • AJAX 安全问题

    我希望能够解决一些关于 AJAX 安全性的问题 这是我试图理解的一个场景 假设我正在使用 AJAX 向页面请求一些半敏感材料 例如 我将把用户的 ID 传递给一个 php 文件 并返回一些关于他们自己的信息 现在 是什么阻止人们模拟此 Ja
  • 检测单选按钮/复选框状态的变化

    我需要可靠地检测页面上单选按钮 复选框的状态变化 以便查看表单是否被修改 现在 这是一个完全独立的脚本 我无法修改任何控制表单的内容 目前 我只能看到两种方法 onchange事件处理程序 有助于处理文本框 文本区域和选择 但不会针对复选框
  • 我可以通过什么方式混合 jQuery 和 vanilla JavaScript

    我有一个用普通 JavaScript 编写的 Web 应用程序 我想用 jQuery 动画来增强它 并使用我在各种 jQuery 插件中找到的一些功能 例如上传 http www uploadify com 可以通过什么方式将 jQuery
  • 为什么省略分号会破坏这段代码?

    或者换句话说 为什么分号插入失败 导致下面的代码被破坏 function Foo Foo prototype bar function console log bar lt missing semicolon function Foo pr
  • 有没有一种方法可以在没有输入的情况下发送表单值

    假设我有以下表格
  • Javascript 将对象推送为克隆

    我将 d3 用于交互式网络应用程序 我需要绑定的数据在交互过程中发生变化 并且由 JSON 变量中的一些选定对象组成 为此 我在 JSON 变量上使用了映射 并进行了一些查询来选择适当的对象 对象被推送到列表中 并且该列表被绑定为新数据 我
  • 将时间戳转换为一个数组

    在应用程序脚本 谷歌表中运行 我从 API 获取时间戳并返回此结果 1 6370611672429312E18 1 63706107263277082E18 我执行此代码并且工作正常 但问题不在数组中 我每次都需要它在数组中 const t
  • 使用 jQuery inputmask 插件范围 0-100

    如何创建 0 到 100 范围内的掩码 document ready function masked inputmask 您可以使用jquery inputmask regex extensions js为了那个原因 你可以找到带有所有扩展
  • 如何将一个数组中的所有项目复制到另一个数组中?

    如何将数组的每个元素 其中元素是对象 复制到另一个数组中 以便它们完全独立 我不想更改一个数组中的元素来影响另一个数组 这里的关键是 数组中的条目是对象 并且 您不希望对一个数组中的对象的修改显示在另一个数组中 这意味着我们不仅需要将对象复
  • 检查用户设备的 GPS 是否开启

    我正在使用 jQuery Mobile 和 PHP 开发一个应用程序 我没有使用 Phonegap 或其他框架 我需要找到用户的geolocation 如果用户设备的 GPS 关闭 那么我无法获取位置 现在我需要查找用户设备的 GPS 是否
  • node.js 模块/导出系统:是否可以将模块导出为函数

    我想在 Dispatch js 中做这样的事情 function handle msg exports handle 这在调用index js中 var dispatch require Dispatch dispatch data 有任何
  • 为什么 call 比 apply 快那么多?

    我想知道是否有人知道why call比apply 在 Chrome 中 速度大约快 4 倍 在 Firefox 中快 30 倍 我什至可以制作自定义原型 apply2 在大多数情况下 运行速度是apply 这个想法取自角度 Function
  • 在反应中访问回调内的 event.target

    我有以下课程片段 constructor props super props this timeout null search e gt clearTimeout this timeout this timeout setTimeout f
  • Firebase + Node.js:错误:找不到 XMLHttpRequest 兼容性库

    Firebase Node js On iOS 安装的 Node js npm 安装 firebase save 节点测试 js 其中 test js 是一个非常简单的连接到 Firebase 的脚本 var firebase requir
  • onPress 方法中箭头函数与普通函数的行为

    正在学习 Native React 并学习更多关于 javascript 的知识 所以我仍然不明白它的行为的很多事情 我使用 TouchableOpacity 及其 onPress 属性创建了一个按钮组件 为了让它工作 我必须发送我想要执行
  • 如何跨多个文件跨越 javascript 命名空间?

    我永远忽略了javascript 几年前我开始使用 jQuery 这样我就可以过得去 但随着我开始更多地进行 TDD 我昨天决定真正深入研究 javascript 之后可能还有咖啡脚本 在我的 ASP NET Web 窗体应用程序中 我有很
  • jQuery Mobile + Admob:轮换?

    我使用 jQuery Mobile 框架创建了一个移动应用程序 所有页面都在index php中加载 使用 div 在每个页面的页脚中 我添加了Admob代码 div div div

随机推荐

  • Cannot resolve plugin org.apache.maven.plugins:maven-install-plugin:2.5.2

    项目场景 今天在创建springboot项目的时候 遇到一个与maven相关的报错 仅此记录一下 防止以后继续踩坑 问题描述 在idea gt settings设置maven的目录信息完后 就遇到了以下报错 原因分析 经排查后发现是自己的本
  • vs code 用户代码片段失效问题

    例如 vue1 scope javascript typescript prefix v1 body new Vue el data description Log output to console 注意 1 如果没有scope的话 试着
  • 【深度学习】yolov5+deepsort 完成计数和行人行人重识别的追踪

    文章目录 前言 1 知识体系 1 1 前置说明 1 2 Sort的工作流程 1 3 deepsort 2 实践应用 3 干货补充 总结 前言 行人重识别是计算机视觉的基本任务之一 首先要有一个detector 检测器来检测到目标 然后将检测
  • Multitor:一款带有负载均衡功能的多Tor实例创建工具

    关于Multitor Multitor是一款带有负载均衡功能的多Tor实例创建工具 Multitor的主要目的是以最快的速度完成大量Tor进程的初始化 并将大量实例应用到我们日常使用的程序中 例如Web浏览器和聊天工具等等 除此之外 在该工
  • Linux配置SSH无密码登录

    下文以配置2台主机无密码登录为例 本机名为master 另外一台机子名为slave1 1 配置主机名 分别修改2台机子的主机名为master和slave1 具体方法 CentOS修改主机名 hostname 2 配置hosts 在2台主机上
  • 媒体查询响应式布局

    移动端样式开始 移动端共用样式开始 media screen and min width 320px and max width 1169px 移动端共用样式结束 768 1169样式开始 1169根据设计图内容宽度来定 media scr
  • odoo13源码-004: models_1

    coding utf 8 Part of Odoo See LICENSE file for full copyright and licensing details Object Relational Mapping module Hie
  • 基于Qt5的计算器设计

    Qt5的信号与槽 描述 信号槽是 Qt 框架引以为豪的机制之一 所谓信号槽 实际就是观察者模式 发布 订阅模式 当某个事件发生之后 比如 按钮检测到自己被点击了一下 它就会发出一个信号 signal 这种发出是没有目的的 类似广播 如果有对
  • Linux下SVN客户端基本使用教程-使用命令

    Subversion SVN 是一个版本控制系统 用于管理文件和目录的历史记录 在 Linux 中 SVN 客户端提供了一组命令 用于与 SVN 服务器交互 检出 提交 更新和管理版本控制项目 以下是一些 Linux SVN 客户端常用的命
  • 【C语言】不使用strcat(字符串连接函数)将两个字符串连接起来。

    解题思路 定义两个字符数组A B 其中A稍大些 将第一个字符串存入A 再将第二个字符串存入B 然后将B中的字符串紧接在A后即可 采用for循环 具体见程序 include
  • matlab矩阵除法

    matlab中除法有四种 作除 右除 对于标量的运算 与 用法一致 a b 或a b表示a除以b 与 用法一致 a b 或a b表示b除以a 对于矩阵运算 a b 表示矩阵a乘矩阵b的逆矩阵 与 a inv b 一致 a b 表示矩阵a的逆
  • 【无标题】nltk安装wordnet出错[nltk_data]Error loading wordnet:<urlopen error [Errno 111]...>

    一 下载wordnet库报错 二 离线下载nltk data 链接 https pan baidu com s 1B70gBI54aERVNcApUrFDXQ 提取码 snec 下载成功后解压得到nltk data的文件夹 三 把nltk
  • 【CAM】CAM(Class Activation Mapping)——可视化CNN的特征定位

    文章目录 一 CAM Class Activation Mapping 二 CAM技术实现 2 1 网络修改 2 2 微调 2 2 特征提取 三 总结 Reference 完整代码见Github https github com capsu
  • c 中内存拷贝函数(C memcpy)详解

    文章转载自 http blog csdn net sszgg2006 article details 7989404 原型 void memcpy void dest const void src unsigned int count 功能
  • python基础----06-----文件读写追加操作

    一 文件编码概念 思考 计算机只能识别 0和1 那么我们丰富的文本文件是如何被计算机识别 并存储在硬盘中呢 答案 使用编码技术 密码本 将内容翻译成0和1存入 常见编码有UTF8 gbk等等 不同的编码 将内容翻译成不同的二进制 二 文件的
  • (STM32CubeMX)超声波模块测距传感器学习笔记

    超声波模块HC SR04 一 简介 1 概念 2 电路连接 3 工作原理 二 STM32CubeMX配置步骤 1 芯片选择 2 引脚配置 3 时钟配置 4 其他配置 三 keil5代码 1 串口重定向 2 超声波模块编写 一 简介 1 概念
  • LVGL学习笔记6 - 输入设备

    目录 1 移植文件 2 移除多余代码 3 输入设备初始化 4 输入设备读回调函数 4 1 LV INDEV TYPE POINTER 4 2 LV INDEV TYPE KEYPAD 4 3 LV INDEV TYPE ENCODER 4
  • opencv SVM

    目录 What is a SVM 官方文档的源代码 函数补充 colRange 和 rowRange RNG 随机数 rng fill 简化 多分类问题 What is a SVM A Support Vector Machine SVM
  • Pytorch使用GPU

    Pytorch使用GPU pytorch默认是不使用gpu的 即使我们已经安装好了支持的cuda版本和cudnn 所以要使用gpu需要在程序里面设置一下 步骤 import torch use gpu torch cuda is avail
  • promise原理:代码实现

    基础代码 function window const PENDING pending const RESOLVED resolved const REJECTED rejected function Promise excutor this