js原生方法promise的实现
一会儿就要回家过年了,再来手写一个promise吧,要不等着下班真的煎熬。。。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="author" content="杨欣">
<title>手写promise</title>
</head>
<body>
<script>
// 第一版
// class _Promise {
// constructor(handler) {
// // 判断参数是否不为函数
// if (typeof handler !== 'function') {
// throw new TypeError(`${handler} is not a function`)
// }
// this.state = 'pending'//初始状态
// this.value = null//最终返回值
// this.reason = null //失败原因
// let _this = this;
// const resolve = function (value) {
// if (_this.state === 'pending') {
// _this.state = 'fulfilled'//改变状态
// _this.value = value//最终返回值赋值
// console.log(_this.value)
// }
// }
// const reject = function (reason) {
// if (_this.state === 'pending') {
// _this.state = 'rejected'//改变状态
// _this.reason = reason//失败原因赋值
// }
// }
// handler(resolve, reject)
// }
// }
// new _Promise((resolve, reject) => {
// resolve(12345)
// })
// // 第二版 代码优化,加then方法,模拟异步操作
// class _Promise {
// constructor(handler) {
// // 判断参数是否不为函数
// if (typeof handler !== 'function') {
// throw new TypeError(`${handler} is not a function`)
// }
// this.initValue()//初始化值
// this.bindThis()//绑定this
// handler(this.resolve, this.reject)
// }
// bindThis() {
// this.resolve = this.resolve.bind(this)
// this.reject = this.reject.bind(this)
// }
// initValue() {
// this.state = 'pending'//初始状态
// this.value = null//最终返回值
// this.reason = null //失败原因
// }
// resolve(value) {
// if (this.state === 'pending') {
// this.state = 'fulfilled'//改变状态
// this.value = value//最终返回值赋值
// }
// }
// reject(reason) {
// if (this.state === 'pending') {
// this.state = 'rejected'//改变状态
// this.reason = reason//失败原因赋值
// }
// }
// then(onFulfilled, onRejected) {
// if (typeof onFulfilled !== 'function') {
// onFulfilled = function (value) {
// return value
// }
// }
// if (typeof onRejected !== 'function') {
// onRejected = function (reason) {
// throw reason
// }
// }
// if (this.state === 'fulfilled') {
// // 模拟异步
// setTimeout(() => {
// onFulfilled(this.value)
// }, 1000);
// }
// if (this.state === 'reject') {
// setTimeout(() => {
// onRejected(this.reason)
// }, 1000);
// }
// }
// }
// new _Promise((resolve, reject) => {
// resolve(1234567)
// }).then((value) => {
// console.log(value, 'value')
// })
// new _Promise((resolve, reject) => {
// setTimeout(() => {
// resolve(1234567)
// }, 1000);
// }).then((value) => {
// console.log(value, 'value')
// })//这种情况下then方法中代码不会打印,因为then方法中state为pending,因此需要添加一个状态判断
// 第三版 添加状态判断,添加链式调用(then方法需要返回promise对象)
class _Promise {
constructor(handler) {
// 判断参数是否不为函数
if (typeof handler !== 'function') {
throw new TypeError(`${handler} is not a function`)
}
this.initValue()//初始化值
this.bindThis()//绑定this
try {
handler(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
bindThis() {
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
}
initValue() {
this.state = 'pending'//初始状态
this.value = null//最终返回值
this.reason = null //失败原因
this.onFulfilledCbs = []//成功回调
this.onRejectedCbs = []//失败回调
}
resolve(value) {
if (this.state === 'pending') {
this.state = 'fulfilled'//改变状态
this.value = value//最终返回值赋值
// resolve成功执行
this.onFulfilledCbs.forEach(fn => fn(this.value))
}
}
reject(reason) {
if (this.state === 'pending') {
this.state = 'rejected'//改变状态
this.reason = reason//失败原因赋值
this.onRejectedCbs.forEach(fn => fn(this.reason))
}
}
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = function (value) {
return value
}
}
if (typeof onRejected !== 'function') {
onRejected = function (reason) {
throw reason
}
}
if (this.state === 'fulfilled') {
// 模拟异步
setTimeout(() => {
onFulfilled(this.value)
});
}
if (this.state === 'reject') {
setTimeout(() => {
onRejected(this.reason)
});
}
let promise2 = new _Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const data = onFulfilled(this.value)
_Promise.resolvePromise(promise2, data, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.state === 'rejected') {
setTimeout(() => {
try {
const data = onRejected(this.reason)
_Promise.resolvePromise(promise2, data, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.state === 'pending') {
this.onFulfilledCbs.push(value => {
setTimeout(() => {
try {
const data = onFulfilled(value)
_Promise.resolvePromise(promise2, data, resolve, reject)
} catch (e) {
reject(e)
}
})
})
this.onRejectedCbs.push(reason => {
setTimeout(() => {
try {
const data = onRejected(this.reason)
_Promise.resolvePromise(promise2, data, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
})
return promise2
}
}
_Promise.resolvePromise = function (promise2, data, resolve, reject) {
// data 与 promise 相等
if (promise2 === data) {
reject(new TypeError('Chaining cycle detected for promise'))
}
let flag = false
if (data instanceof _Promise) {
// 判断 data 为 Promise
data.then(
value => {
_Promise.resolvePromise(promise2, value, resolve, reject)
},
reason => {
reject(reason)
}
)
} else if (data !== null && (typeof data === 'object' || typeof data === 'function')) {
// data 为对象或函数
try {
const then = data.then
if (typeof then === 'function') {
then.call(
data,
value => {
if (flag) return
flag = true
_Promise.resolvePromise(promise2, value, resolve, reject)
},
reason => {
if (flag) return
flag = true
reject(reason)
}
)
} else {
if (flag) return
flag = true
resolve(data)
}
} catch (e) {
if (flag) return
flag = true
reject(e)
}
} else {
resolve(data)
}
}
new _Promise((resolve, reject) => {
setTimeout(() => {
resolve(1234567)
}, 1000);
}).then((value) => {
console.log(value, 'value')
return 11111
}, (reason) => {
console.log(reason, 'reason')
}).then((res) => {
console.log(res, 'res')
})
</script>
</body>
</html>
js原生方法promise的实现的更多相关文章
- js 原生方法获取所有兄弟节点
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...
- 【es6】js原生的promise
JavaScript 是单线程的,这意味着任何两句代码都不能同时运行,它们得一个接一个来.在浏览器中,JavaScript 和其他任务共享一个线程,不同的浏览器略有差异,但大体上这些和 JavaScr ...
- JS原生方法实现瀑布流布局
html部分(图片都是本地,自己需要改动图片) p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 30.0px Consolas; color: #2b7ec ...
- 像jq那样获取对象的js原生方法
使用过jq的童鞋非常喜欢jq获取对象的方法,只要$()就可以获取,在此我封装一个js获取对象的方法 [注意]只对chrome,Firefox,opera,Safari,ie8及ie8以上版本有效 fu ...
- JS原生方法被覆盖后的恢复办法
alert 被覆盖 今天装修博客园,调试了下JS代码发现 alert() 方法被官方覆盖了,查看源码得知 alert 的功能被替换成了 console.log. 恢复 var _frame = doc ...
- js原生方法传参的细节(面试必问)
废话不说,直接上题. slice(),接收两个参数,第一个为开始index(从0开始),第二个为结束的index(也是从0开始,但是不包括index本身,只到index-1).返回值是截取的数组,原数 ...
- JS原生方法实现jQuery的ready()
浏览器加载页面的顺序: 1. 解析HTML结构 2. 加载外部脚本和样式表文件 3. 解析并执行脚本代码 4. 构造HTML DOM模型==ready() 5. 加载图片等组件 6. 页面加载完毕== ...
- 图片首尾平滑轮播(JS原生方法—节流)<原创>
首先给出HTML代码,要注意轮播图片表(#list)末尾加上第一个图片1.jpg,在首部加上最后一个图片5.jpg. <!DOCTYPE html> <html lang=" ...
- 【笔记】js原生方法 在元素外部或内部实现添加元素功能(类似jq 的 insert 和 append)
介绍的这个方法是:insetAdjacentHTML() 方法 此方法接收两个参数: 第一个参数必为下列值: beforebegin:在调用的元素外部的前面添加一个目标元素 afterend:在调用元 ...
随机推荐
- Vue3.0响应式原理
Vue3.0的响应式基于Proxy实现.具体代码如下: 1 let targetMap = new WeakMap() 2 let effectStack = [] //存储副作用 3 4 const ...
- “3+3”看华为云FusionInsight如何引领“数据新基建”持续发展
摘要:一个统一的现代化的数据基建需要三类架构来实践三种不同的应用场景. 近期,美国知名科技企业风投机构A16Z总结出一套通用的技术架构服务,分为以下三种场景. 一.数据基建架构全景 数据流向显示,左侧 ...
- 问题记录-CoordinatorLayout+WebView使用遇到的问题
需求背景: 使用CoordinatorLayout+viewpager+tablayout+webview实现首页折叠效果. 使用问题: 在使用过程中首页的页面为原生/h5混合页,在原生页面正常,嵌套 ...
- JS控制Video播放器(快进、后退、播放、暂停、音量大小)
思路: 一.首先监听触发事件. 比如:向上键对应的keyCode为38,向下键对应的keyCode为40,向左键对应的keyCode为37,向右键对应的keyCode为39,空格键对应的keyCode ...
- web安全入门--入门条件
介绍:网络安全由习大大提出,是继海.陆.空.外太空的第五大作战领域,也是一个关系国家安全和主权.社会稳定.民族文化继承和发扬的重要问题.其重要性,正随着全球信息化步伐的加快越来越重要.接下来,我向大家 ...
- 深度分析:理解Java中的多态机制,一篇直接帮你掌握!
Java中的多态 1 多态是什么 多态(Polymorphism)按字面的意思就是"多种状态".在面向对象语言中,接口的多种不同的实现方式即为多态.用白话来说,就是多个对象调用同一 ...
- 20-SAP PI开发手册-ERP发布服务供外部系统调用(sproxy代理类)
一. 接口内容 接口详细信息 1. 字段对应关系 发送字段对应关系 返回字段对应关系 2. 报文信息 传入报文(报文结构,外围系统提供) 1 <?xml version=" ...
- 在CorelDRAW2019创建对称绘图模式
对称绘图模式是CorelDRAW 2018推出的全新功能,在2019的版本中又得到了极大的完善,通过对称绘图模式可以创建平衡.和谐.独一无二的效果,对称在大自然中随处可见,因此设计元素很可能将依靠于它 ...
- H5系列之video自己编写控制栏
首先来了解一下 video, video呢,是H5 的标签,别人说的 H5播放器,没错 就是他了,利用video标签,可以实现视频播放. 但是啊,你会发现,在不同的浏览器上,播放器的 控制栏,都是不一 ...
- vim进入粘贴模式
最近使用linux的vim编辑器编写程序时,遇到一些繁琐的模板想要复制粘贴进去,直接进入插入模式点复制,复制出来的格式不对没办法运行 解决办法: 这是因为 Vim 自动缩进了,按照如下设置可以解决该问 ...