javascript --- 手写Promise、快排、冒泡、单例模式+观察者模式

手写promise

一种异步的解决方案, 参考

Promise代码基本结构

function Promise(executor){this.state = 'pending';this.value = undefined;this.reason = undefined;function resolve(){}function reject(){}
}
module.exports = Promise

state保存的是当前的状态,在Promise状态发展只有以下两种模式且不可逆:

pending - 等待态
resolved - 成功态
rejected - 失败态

从上可知,状态只能由pending变为resolved(执行resolve)或pending变为rejected(执行reject)

这就引出了resolve和reject的功能

function Promise(executor){this.state = 'pending'this.value = undefinedthis.reason = undefinedfunction resolve(value){this.state = 'resolved'this.value = value}function reject(reason){this.state = 'rejected'this.reason = reason}executor(resove, reject)
}

then方法的实现

当Promise的状态发生了改变,不论是成功或是失败都会调用then方法

let p = new Promise((resolve, reject)=>{setTimeout(()=>{resolve(1)},50)
})
p.then(data=>{console.log(data)})

可以得出then的方法,由于then方法是每个实例所以共有,因此可以将其写在原型链上:

  • 接受2个参数,成功的回调onFulfilledonRejected
    • 两个函数分别在resolved状态下和rejected状态下执行
Promise.prototype.then = function(onFulfilled, onRejected){if(this.state === 'resolved'){onFulfilled(this.value)}if(this.state === 'rejected'){onRejected(this.reason)}
}

当你写出了以上的代码,在同步的情况下执行完全没有问题. 但是在异步的情况下,流程如下:

  • 函数执行new Promise,当遇到setTimeout时,会将其推入一个异步队列中
  • 然后执行p.then: 浏览器会顺着原型链找到Promise.prototype.then发现此时的状态是pending,故不做任何处理,结束同步处理
  • 开始执行异步队列里面的setTimeout,执行resovle(1).

异步方法的实现

处理异步方法的关键是,在Promise.prototype.then方法中,当状态为pending时,可以将处理函数作为变量存储起来,这样当异步过后,执行resolve时,可以在内存中找到相应的处理函数并对其进行执行.

这就需要我们修改Promise构造函数

function Promise(exector){this.state = 'pending'this.value = undefinedthis.reason = undefinedthis.onResolvedCallbacks = []	// 用于存储成功的回调this.onRejectedCallbacks = []	// 用于存储失败的回调function resolve(value){if(this.state === 'pending'){this.state = 'resolved'this.value = valuethis.onResolvedCallbacks.forEach(resolved=> resolved(value))}}function reject(reason){if(this.state === 'pending'){this.state = 'rejected'this.reason = reasonthis.onRejectedCallbacks.forEach(rejected=> rejected(reason))}}
}// 修改 Promise.prototype.then
Promise.prototype.then = function (onFulfilled, onRejected){if(this.state === 'resolved'){onFulFilled(this.value)}if(this.state === 'rejected'){onRejected(this.reason)}// 异步: 将回调函数放入内存中.if(this.state === 'pending'){ if(typeof onFulfilled === 'function'){this.onResolvedCallbacks.push(onFulfilled)}if(typeof onRejected  === 'function'){this.onRejectedCallbacks.push(onRejected)}}
}

当涉及到异步,使用this时要绝对小心

在使用setTimeout,里面回调使用的函数中的this是指向window的(通过debugger调试可以获得).这就需要在一开始时,将指向实例的this保存下来.

function Promise(exector){let _this = this_this.state = 'pending'_this.value = undefined_this.reason = undefined_this.onResovledCallbacks = []_this.onRejectedCallbacks = []function resolve(value){_this.state = 'resolved'_this.value = value_this.onResolvedCallbacks.forEach(resolved => resolved(value))}function reject(reason){_this.state = 'rejected'_this.reason = reason_this.onRejectedCallbacks.forEach(rejected=> rejected(reason))}exector(resolve, reject)
}
Promise.prototype.then = function(onFulfilled, onRejected){if(this.state === 'resolved'){onFulfilled(this.value)}if(this.state === 'rejected'){onRejected(this.reason)}if(this.state === 'pending'){if(typeof onFulfilled === 'function'){this.onResolvedCallbacks.push(onFulfilled)}if(typeof onRejected === 'function'){this.onRejectedCallbacks.push(onRejected)}}
}

快排

思路: 将每次的第一个元素作为基准,将比基准小的放在left数组中,比基准大的放在right数组中.然后返回[left, pivot,right]

function qSort(arr){let pivot,left = [],right = []function loop(arr){pivot = arr[0]left = []right = []for(let i=0, len = arr.length; i < len; i++){if(arr[i] > pivot){right.push(arr[i])} else{left.push(arr[i])}}return loop(left).concat(pivot, loop(right))}return loop(arr)
}

冒泡排序

思路:

  • 记录待排序的数组长度 len
  • 当len大于0时,会进入循环
    • 会使用nextLen保存下次循环的长度.(为undefined会跳出循环)
    • 每次循环都从第0号位开始,最后到len.
    • 比较左右2边的元素
      • 左 > 右: 则交换左右两边的位置,并将nextLen置为当前的下标
    • 每次到循环结束,都会将len设为nextLen
function bubbleSort(arr){let len = arr.length;while(len > 0){let tmp,nextLenfor(let i =0 ; i< len; i++){if(arr[i]>arr[i+1]){tmp = arr[i]arr[i] = arr[i+1]arr[i+1] = tmpnextLen = i}len = nextLen}}return arr
}

单例模式实现 发布/订阅 模式

  • 单例模式即只有一个实例

  • 发布订阅模式,即使用addDep添加依赖.使用notify

class Observer{constructor(){this.events ={}}addDep(tag, handler){if(Array.isArray(this.events[tag])){// 是一个数组this.events[tag].push(handler)}else{this.events[tag] = [handler]}}notify(tag, params){this.events[tag].forEach(fn => fn(params))}
}

以上实现了一个简单的观察者模式,下面使用单例模式对其进行改造.

简单的说就是在使用new Observer时,返回的是同一个实例.给构造函数添加一个获取单例的方法

class Observer{constructor(){this.events = {}this.instance = null}
}
Observetr.getInstance = function (){if(this.instance == null){this.instance = new Observer}return this.instance
}let o1 = Observetr.getInstance()
let o2 = Observetr.getInstance()
console.log(o1 === o2)		// true

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/250262.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyCharm 通过Github和Git上管理代码

1.Pycharm中设置如图: 2.配置Git,通过网页 https://www.git-scm.com/download/win 下载 3. 转载于:https://www.cnblogs.com/0909/p/9956406.html

【BZOJ】2395: [Balkan 2011]Timeismoney

题解 最小乘积生成树&#xff01; 我们把&#xff0c;x的总和和y的总和作为x坐标和y左边&#xff0c;画在坐标系上 我们选择两个初始点&#xff0c;一个是最靠近y轴的A&#xff0c;也就是x总和最小&#xff0c;一个是最靠近x轴的B&#xff0c;也就是y总和最小 连接两条直线&…

http --- http与https相关概念小结

网络协议 参考 HTTP的特性 HTTP协议构建于TCP/IP协议之上,是一个应用层协议,默认端口是80HTTP是无连接无状态的 HTTP报文 请求报文 HTTP协议是以ASCII码传输,建立在 TCP/IP 协议之上的应用层规范。规范把HTTP请求分为三个部分:状态行、请求头、消息主体。 <method>…

Spring AOP注解方式实现

简介 上文已经提到了Spring AOP的概念以及简单的静态代理、动态代理简单示例&#xff0c;链接地址&#xff1a;https://www.cnblogs.com/chenzhaoren/p/9959596.html 本文将介绍Spring AOP的常用注解以及注解形式实现动态代理的简单示例。 常用注解 aspect&#xff1a;定义切面…

享元模式-Flyweight(Java实现)

享元模式-Flyweight 享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。 本文中的例子如下: 使用享元模式: 小明想看编程技术的书, 就到家里的书架上拿, 如果有就直接看, 没有就去买一本, 回家看. 看完了就放到家里…

算法 --- 回溯法

回溯法 参考 - 剑指Offer 回溯法可以看成蛮力法的升级版,它从解决问题每一步的所有可能选项里系统地选择出一个可行的解决方案. 回溯法解决的问题的特性: 可以形象地用树状结构表示: 节点: 算法中的每一个步骤节点之间的连接线: 每个步骤中的选项,通过每一天连接线,可以到达…

013.Zabbix的Items(监控项)

一 Items简介 Items是从主机里面获取的所有数据&#xff0c;可以配置获取监控数据的方式、取值的数据类型、获取数值的间隔、历史数据保存时间、趋势数据保存时间、监控key的分组等。通常情况下item由key参数组成&#xff0c;如监控项中需要获取cpu信息&#xff0c;则需要一个对…

Cookie 和 Session的区别

pass 下次再写转载于:https://www.cnblogs.com/nieliangcai/p/9073520.html

算法 --- 记一道面试dp算法题

题目: 给定一个数组(长度大于1),如下 let a [1,4,3,4,5] // 长度不确定,数值为整数要求写一个函数,返回该数组中,除本身数字之外其他元素的成积.即返回如下: // 过程[4*3*4*5, 1*3*4*5, 1*4*4*5, 1*4*3*5, 1*4*3*4] // 结果[240, 60, 80, 60, 48]题目要求不使用除法,且时间…

编码

一、什么是编码&#xff1f;首先&#xff0c;我们从一段信息即消息说起&#xff0c;消息以人类可以理解、易懂的表示存在。我打算将这种表示称为“明文”&#xff08;plain text&#xff09;。对于说英语的人&#xff0c;纸张上打印的或屏幕上显示的英文单词都算作明文。其次&a…

ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(10)之素材管理

源码下载地址&#xff1a;http://www.yealuo.com/Sccnn/Detail?KeyValuec891ffae-7441-4afb-9a75-c5fe000e3d1c 素材管理模块也是我们这个项目的核心模块&#xff0c;里面的增删查改都跟文章管理模块相同或者相似&#xff0c;唯一不同点可能是对附件的上传处理&#xff0c;但…

javascript --- [express+ vue2.x + elementUI]登陆的流程梳理

说明 涉及到以下知识点: 登陆的具体流程express、vue2.x、elementUI、axios、jwt、assert 登陆方面的API使用中间件的使用前后端通过http状态码,进行响应的操作(这里主要是401)密码验证(bcrypt的hashSync方法对明文密码进行加密,compareSync方法对加密的密码进行验证)token的…

设计模式---装饰模式

今天学习了装饰模式&#xff0c;做个笔记。。装饰模式的基础概念可以参考&#xff1a;https://blog.csdn.net/cjjky/article/details/7478788 这里&#xff0c;就举个简单例子 孙悟空有72变&#xff0c;但是它平时是猴子&#xff0c;遇到情况下&#xff0c;它可以变成蝴蝶等等 …

springMvc 注解@JsonFormat 日期格式化

1&#xff1a;一定要加入依赖,否则不生效&#xff1a; <!--日期格式化依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version>&…

Git很简单--图解攻略

Git Git 是目前世界上最先进的分布式版本控制系统&#xff08;没有之一&#xff09;作用 源代码管理为什么要进行源代码管理? 方便多人协同开发方便版本控制Git管理源代码特点 1.Git是分布式管理.服务器和客户端都有版本控制能力,都能进行代码的提交、合并、. 2.Git会在根…

css --- 使用scss生成常用的基本css样式

"工具样式"的概念和 SASS(SCSS) 在webpack中使用sass 安装sass和sass-loader $ npm i sass sass-loader由于使用了脚手架,安装完毕后重启前端即可 样式重置 其实就是样式的初始化 // reset* {box-sizing: border-box; // 以边框为准. css3盒模型outline: none;…

vc/vs开发的应用程序添加dump崩溃日志转

原贴地址&#xff1a;https://blog.csdn.net/wangkui1331/article/details/78029940 vc/vs开发的应用程序出现崩溃的时候&#xff0c;由于没有任何记录&#xff0c;导致开发人员很难追踪&#xff0c;但是添加dump文件后&#xff0c;就可以免除这些烦恼 1.添加方法 &#xff08;…

51 nod 1127最短的包含字符串(尺取法)

1127 最短的包含字符串 收藏关注给出一个字符串&#xff0c;求该字符串的一个子串S&#xff0c;S包含A-Z中的全部字母&#xff0c;并且S是所有符合条件的子串中最短的&#xff0c;输出S的长度。如果给出的字符串中并不包括A-Z中的全部字母&#xff0c;则输出No Solution。Input…

Java --- 基础学习Ⅰ

第一章 开发前言 位、字节 位(bit): 一个数字0或一个数字1,代表一位 字节(Byte): 每逢8位是一个字节,这时数据存储的最小单位 1 Byte 8 bit 1 KB 1024 Byte 1 MB 1024 KB 1 GB 1024 MB 1 TB 1024 GB 1 PB 1024 TB MS-DOS(Microsoft Disk Operating System) 第二章 Ja…

JSON 数据重复 出现$ref

JSONArray 类型 如果我们往里面add数据的时候 如果数据相同&#xff0c;那么就会被替换成 $ref: 也就是被简化了 因为数据一样所直接 指向上一条数据 循环引用&#xff1a;当一个对象包含另一个对象时&#xff0c;fastjson就会把该对象解析成引用。引用是通过$ref标示的&am…