JavaScript模拟实现Promise功能的示例代码

模拟Promise的功能,  按照下面的步骤,一步一步

1. 新建是个构造函数

2. 传入一个可执行函数 函数的入参第一个为 fullFill函数 第二个为 reject函数; 函数立即执行, 参数函数异步执行

3. 状态一旦更改就不可以变更 只能 pending => fulfilled 或者 pending => rejected

4. then 的时候要处理入参的情况 successCallback 和failCallback 均可能为非函数

默认的 failCallback 一定要将异常抛出, 这样下一个promise便可将其捕获 异常冒泡的目的

5. then 中执行回调的时候要捕获异常 将其传给下一个promise

  • 如果promise状态未变更 则将回调方法添加到对应队列中
  • 如果promise状态已经变更 需要异步处理成功或者失败回调
  • 因为可能出现 回调结果和当前then返回的Promise一致 从而导致死循环问题

6. catch只是then的一种特殊的写法 方便理解和使用

7. finally 特点

  • 不过resolve或者reject都会执行
  • 回调没有参数
  • 返回一个Promise 且值可以穿透到下一个then或者catch

8. Promise.resolve, Promise.reject 根据其参数返回对应的值 或者状态的Promise即可

9. Proise.all 特点

  • 返回一个Promise
  • 入参是数组 resolve的情况下出参也是数组 且结果顺序和调用顺序一致
  • 所有的值或者promise都完成才能resolve 所有要计数
  • 只要有一个为reject 返回的Promise便reject

10. Proise.race 特点

  • 返回一个Promise
  • 入参是数组 那么出参根据第一个成功或者失败的参数来确定
  • 只要有一个resolve 或者reject 便更改返回Promise的状态
const PENDING = 'pending' //等待
const FULFILLED = 'fulfilled' //成功
const REJECTED = 'rejected' //失败

const fulfilledCallback = [] //成功回调函数
const rejectedCallback = []  //失败回调函数

class MyPromise {

    constructor (executor) {

        try{
            executor(this.resolve, this.reject)
        } catch (e){
            this.reject(e)
        }
    }

    status = PENDING//promise的状态
    value = undefined//成功之后的值
    reason = undefined//失败之后的值
    fulfilledCallback = [] //成功回调函数
    rejectedCallback = []  //失败回调函数
    resolve = value => {
        //如果状态不是等待, 阻止程序继续往下执行
        if(this.status !== PENDING){
            return
        }
        this.status = FULFILLED
        this.value = value
        //判断成功回调是否存在,如果存在, 调用
        // this.fulfilledCallback && this.fulfilledCallback(this.value)
        while(this.fulfilledCallback.length) this.fulfilledCallback.shift()()

    }
    reject = reason => {
        //如果状态不是等待, 阻止程序继续往下执行
        if(this.status !== PENDING){
            return
        }
        this.status = REJECTED
        this.reason = reason
        //判断失败回调是否存在,如果存在, 调用
        // this.rejectedCallback && this.rejectedCallback(this.reason)
        while(this.rejectedCallback.length) this.rejectedCallback.shift()()
    }
    then = (fulfilledCallback, rejectedCallback) => {
        fulfilledCallback = fulfilledCallback ? fulfilledCallback : value => value
        rejectedCallback = rejectedCallback ? rejectedCallback : reason => {throw reason}
        let promise2 = new MyPromise((resolve, reject) => {

            //判断状态
            if(this.status === FULFILLED){
                setTimeout(() => {
                    try {
                        //判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
                        //如果是普通值,直接调用resolve
                        let x = fulfilledCallback(this.value)
                        //外面加载完,才能获取到promise2,用异步解决
                        resolvePromise(promise2,x,resolve, reject)
                    } catch (error) {
                        reject(error)
                    }

                },0)

            }else if(this.status === REJECTED){

                setTimeout(() => {
                    try {
                        //判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
                        //如果是普通值,直接调用resolve
                        let x = rejectedCallback(this.reason)
                        //外面加载完,才能获取到promise2,用异步解决
                        resolvePromise(promise2,x,resolve, reject)
                    } catch (error) {
                        reject(error)
                    }

                },0)
            }else{
                //等待状态
                this.fulfilledCallback.push(() => {
                    setTimeout(() => {
                        try {
                            //判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
                            //如果是普通值,直接调用resolve
                            let x = fulfilledCallback(this.value)
                            //外面加载完,才能获取到promise2,用异步解决
                            resolvePromise(promise2,x,resolve, reject)
                        } catch (error) {
                            reject(error)
                        }

                    },0)
                });
                this.rejectedCallback.push(() => {
                    setTimeout(() => {
                        try {
                            //判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
                            //如果是普通值,直接调用resolve
                            let x = rejectedCallback(this.reason)
                            //外面加载完,才能获取到promise2,用异步解决
                            resolvePromise(promise2,x,resolve, reject)
                        } catch (error) {
                            reject(error)
                        }

                    },0)
                });
            }
        })
        return promise2
    }

    static all (array) {
        let result= []
        let index = 0;

        return new MyPromise((resolve, reject) => {

            function addData (key, value) {
                result[key] = value
                index++
                if (index === array.length) {
                    resolve(result)
                }
            }

            for (let i = 0; i < array.length; i++) {

                if (array[i] instanceof MyPromise) {
                    //promise对象
                    array[i].then(value => addData(i, value), reason => reject(reason))
                } else {
                    //普通值, 放到数组里
                    addData(i, array[i])
                }
            }
        })

    }

    static resolve (value) {
        if(value instanceof MyPromise) return value
        return new MyPromise(resolve => resolve(value))

    }

    finally (callback) {
        return this.then(value => {
            return MyPromise.resolve(callback()).then(() => value)
        }, reason => {
            return MyPromise.resolve(callback()).then(() => {throw reason})
        })

    }

    catch (rejectedCallback) {
        return this.then(undefined, rejectedCallback)
    }

}

function resolvePromise(promise2,x,resolve, reject){

    if(x === promise2){
        return reject(new TypeError('啦啦啦啦'))
    }
    if(x instanceof MyPromise){
        //是promise
        //往下直接传
        x.then(resolve,reject)
    }else{
        //普通值
        resolve(x)
    }
}

module.exports = MyPromise;

到此这篇关于JavaScript模拟实现Promise功能的示例代码的文章就介绍到这了,更多相关JavaScript实现Promise功能内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Promise 链式调用原理精简示例

    目录 前言 代码 经典案例 解析 第一步 第二步 分析说明,此过程需结合上文中的案例一起阅读 总结 前言 在面试的过程中,总有一些面试官会问你,手写一个简易版的Promise得行不,得行的话就写一个出来看看,啪一哈,就把纸和笔给了你. 我们思索半天就写出来了个下面这个. 哦豁,高薪张开了它的翅膀,远离了我们. class Promise { constructor (resolve, reject) {} resolve () {} reject (){} then () {} catch ()

  • Promise对象all与race方法手写示例

    目录 前言 Promise.all 介绍 手写 Promise.race 介绍 手写 前言 在理解了手写promsie.then的方法后,再来看它的其他方法,感觉真的简单了不少. Promise.all 介绍 Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例. const p = Promise.all([p1, p2, p3]); 上面代码中,Promise.all()方法接受一个数组作为参数,p1.p2.p3都是 Promise 实例.另外

  • 详解JavaScript如何实现一个简易的Promise对象

    目录 前言 Promise的基础结构与用法 使用class类实现promise对象 写在最后 前言 实现一个简易的Promise对象,我们首先要了解几个相关的知识点: Promise对象的状态: pending(进行中).fulfilled(已成功)和rejected(已失败).只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态.这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变. Promise的参数: Promise构造函数接收一个函

  • JavsScript中Promise的错误捕获详解

    目录 我们需要在异步任务中准确的进行错误捕获,以便我们可以知道错误出在什么地方 我们再讨论then方法中的第二个参数和Promise.catch方法的区别 题: then方法的连续调用,怎么能够知道是第几个then方法报错了呢. 总结 我们需要在异步任务中准确的进行错误捕获,以便我们可以知道错误出在什么地方 如果对Promise和trycatch不够理解的话,很多时候会出现Promise中的错误无法被捕获的情况,本文来讨论这些情况 try catch try catch 只能捕获当前上下文中的错

  • 捕获未处理的Promise错误方法

    为了保证可读性,本文采用意译而非直译,并且对源代码进行了大量修改.另外,本文版权归原作者所有,翻译仅用于学习. 使用Promise编写异步代码时,使用reject来处理错误.有时,开发者通常会忽略这一点,导致一些错误没有得到处理.例如: function main() { asyncFunc() .then(···) .then(() => console.log('Done!')); } 由于没有使用catch方法捕获错误,当asyncFunc()函数reject时,抛出的错误则没有被处理.

  • JS使用Promise时常见的5个错误总结

    目录 1.避免 Promise 地狱 2.在 Promise 中使用 try/catch 块 3.在 Promise 块内使用异步函数 4.在创建 Promise 后立即执行 Promise 块 5.不一定使用 Promise.all() 方法 总结 Promise 提供了一种优雅的方法来处理 JS 中的异步操作.这也是避免“回调地狱”的解决方案.然而,并没有多少开发人员了解其中的内容.因此,许多人在实践中往往会犯错误. 在本文中,介绍一下使用 promise 时的五个常见错误,希望大家能够避免

  • JavaScript面试必考之实现手写Promise

    目录 Promise手写 框架 完整代码 测试 resolve reject Promise手写 Promise作为面试必考题,Promise的手写也是面试官必问的问题,所以对于Promise我们一定要了解透彻 框架 (function(window) { MyPromise.prototype.then = function (onResolved, onRejected) {} MyPromise.prototype.catch = function (onRejected) {} func

  • Promise抛出错误解决基础示例详解

    目录 then catch finally Promise.resolve Promise.reject then then 函数的会接收两个回调函数,一个是 onFulfilled 函数,一个是 onRejected 函数 如果这两个回调函数没有写返回值,默认会 return undefined; 进入下一个函数的 onFulfilled 函数中 const p = new Promise((resolve, reject) => { resolve(22); }); p.then( (suc

  • JavaScript实现九宫格抽奖功能的示例代码

    目录 效果图 实现流程 主要代码 效果图 话不多说,直接上效果: 实现流程 主要流程为: 1. 根据效果图,构建静态页面 2. 获取元素(自带的属性) 3. 绑定事件 4. 事件触发之后 4.1 所有的li元素 在指定的时间间隔下 颜色随机变化 4.2 延时器 2秒后 清除定时器 4.3 在清除定时器之后,所有的li背景色复位,随机选一个 主要代码 <!DOCTYPE html> <html lang="en"> <head> <meta ch

  • php 实现收藏功能的示例代码

    整理文档,搜刮出一个php 实现收藏功能的示例代码,稍微整理精简一下做下分享. HTML: <a class = "x" id="{$photo.id}" uid="{$Think.session.uid}" status = "{$collect_pic}" href = "javascript:void(0);"> <if condition = "$collect_num

  • koa2实现登录注册功能的示例代码

    本文介绍了koa2实现登录注册功能的示例代码,分享给大家,具体如下: 这个主要结合前几天的内容,做个实际案例的效果 版本: 项目结构: 前几天,我们把注册和登录的页面demo实现了,今天我们主要实现这么几个内容 注册新用户 判断该邮箱是否注册过 登录判断是否注册过 登录时的密码的正确 本文代码地址:https://github.com/xiaqijian/koa2-lessons/tree/master/lesson6 明天,我们将利用session实现登录状态判断 今天的这篇是在之前的代码基础

  • 原生JavaScript实现滑动拖动验证的示例代码

    本文介绍了原生JavaScript实现滑动拖动验证的示例代码,分享给大家,具体如下: 通常,我们为了防止用户恶意提交表单,会让用户在提交前完成滑动拖动验证,有时候这也能起到一丝反爬的作用. 实现滑动验证的方式当然不止一种,这里我们直接使用原生 JavaScript 来实现. 现在,你可以在这里 看到完整的源码. 原生实现 原生 JavaScript 的实现,主要是通过监听鼠标事件来对 DOM 进行一系列的操作. 滑块验证的结构主要分为四个部分:轨道.滑块.背景和文案,我们可以使用下面的 HTML

  • Spring boot+mybatis+thymeleaf 实现登录注册增删改查功能的示例代码

    本文重在实现理解,过滤器,业务,逻辑需求,样式请无视.. 项目结构如下 1.idea新建Spring boot项目,在pom中加上thymeleaf和mybatis支持.pom.xml代码如下 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3

  • Selenium之模拟登录铁路12306的示例代码

    最近接触了一些selenium模块的相关知识,觉得还挺有意思的,于是决定亲自尝试写一些爬虫程序来强化selenium模块(一定要多尝试.多动手.多总结).本文主要使用python爬虫来模拟登录铁路12306官网.这儿得吐槽一句,铁路12306网站的反爬机制做的还是比较好. 话不多说,下面跟小墨一起来学习如何通过爬虫来实现铁路12306的登录. 一. 验证码破解 当我们输入账号和密码后,在点击登录按钮之前,还需要对验证码进行操作.对验证码的识别,已经有相关的处理平台,我们只需要借助第三方平台即可.

  • JavaScript实现串行请求的示例代码

    使用async和await var fn = async function(promiseArr) { for(let i = 0,len = arr.length; i<len; i++) { currentPromise = (promiseArr[i] instanceOf Promise) ? promiseArr[i] : Promise.resolve(promiseArr[i]); var result = await currentPromise; console.log(res

  • MySQL查询字段实现字符串分割split功能的示例代码

    目录 问题背景 场景模拟 方法实现 SUBSTRING_INDEX LENGTH REPLACE SQL解析 问题背景 查询MySQL中用逗号分隔的字段[a,b,c]是否包含[a] 场景模拟 现有表[ec_logicplace],如下图所示: 要求判断数值[1]是否存在于表[ec_logicplace]中的[actual_place_id]中 方法实现 首先将[actual_place_id]字段用逗号拆分查询出来 通用模板为: SELECT SUBSTRING_INDEX( SUBSTRING

  • Java实现断点下载功能的示例代码

    目录 介绍 效果 前端代码 后端代码 介绍 当下载一个很大的文件时,如果下载到一半暂停,如果继续下载呢?断点下载就是解决这个问题的. 具体原理: 利用indexedDb,将下载的数据存储到用户的本地中,这样用户就算是关电脑那么下次下载还是从上次的位置开始的 先去看看本地缓存中是否存在这个文件的分片数据,如果存在那么就接着上一个分片继续下载(起始位置) 下载前先去后端拿文件的大小,然后计算分多少次下载(n/(1024*1024*10)) (结束位置) 每次下载的数据放入一个Blob中,然后存储到本

  • Android实现显示和隐藏密码功能的示例代码

    在前端中我们知道用javascript就可以可以很容易实现,那么在Android中怎么实现这个功能呢? Java代码 package com.example.test2; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.text.method.HideReturnsTransformationMethod; import android.text.method.Pa

随机推荐