手写符合Promise/A+规范的Promise
const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected"; function MyPromise(fn){
const that = this;
that.state = PENDING;
that.value = null;
that.resolvedCallbacks = [];
that.rejectedCallbacks = [];
function resolve(value){
// 判断传入的值是否为 Promise 类型
if( value instanceof MyPromise){
return value.then(resolve, reject)
}
// 为了保证函数的执行顺序,需要将两个函数体代码使用 setTimeout 包裹起来
setTimeout(()=>{
// 只有等待状态才可以改变状态
if(that.state == PENDING){
// 将当前状态更改为对应状态,并且将传入的值赋值给 value
that.state = RESOLVED;
that.value = value;
// 遍历回调数组并执行
that.resolvedCallbacks.map(cb => cb(that.value));
}
},0) }
function reject(value){
setTimeout(()=>{
if(that.state == PENDING){
that.state == REJECTED;
that.value = value;
that.rejectedCallbacks.map( cb => cb(that.value));
}
})
}
try {
fn(resolve, reject)
} catch (e) {
reject(e)
} }
MyPromise.prototype.then = function(onFulfilled, onRejected){
const that = this;
// 判断两个参数是否为函数类型, 这两个参数是可选参数
// 当参数不是函数类型时,需要创建一个函数赋值给对应的参数,同时也实现了透传
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : r => {throw r};
if(that.state === PENDING){
// 返回了一个新的 Promise 对象,并在 Promise 中传入了一个函数
// 规范规定,执行 onFulfilled 或者 onRejected 函数时会返回一个 x,并且执行 Promise 解决过程,这是为了不同的 Promise 都可以兼容使用,比如 JQuery 的 Promise 能兼容 ES6 的 Promise
return (promise2 = new MyPromise((resolve, reject)=>{
that.resolvedCallbacks.push(()=>{
try {
const x = onFulfilled(that.value)
resolutionProcedure(promise2, x, resolve, reject)
}catch (r) {
reject(r)
}
});
that.rejectedCallbacks.push(()=>{
try {
const x = onRejected(that.value)
resolutionProcedure(promise2, x, resolve, reject)
} catch (r) {
reject(r)
}
});
}))
}
if(that.state === RESOLVED){
return (promise2 = new MyPromise((resolve, reject)=>{
setTimeout(()=>{
try {
const x = onFulfilled(that.value)
resolutionProcedure(promise2, x, resolve, reject)
} catch (reason) {
reject(r)
}
})
}))
}
if(that.state === REJECTED){
return (promise2 = new MyPromise((resolve, reject)=>{
try {
const x = onRejected(that.value);
resolutionProcedure(promise2, x, resolve, reject)
}catch(r){
reject(r)
}
}))
} function resolutionProcedure(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Error'))
}
if (x instanceof MyPromise) {
x.then(function(value) {
resolutionProcedure(promise2, value, resolve, reject)
}, reject)
}
// 创建一个变量 用于判断是否已经调用过函数
// let called = false; // if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
// try {
// let then = x.then
// if (typeof then === 'function') {
// then.call(
// x,
// y => {
// if (called) return
// called = true
// resolutionProcedure(promise2, y, resolve, reject)
// },
// e => {
// if (called) return
// called = true
// reject(e)
// }
// )
// } else {
// resolve(x)
// }
// } catch (e) {
// if (called) return
// called = true
// reject(e)
// }
// } else {
// resolve(x)
// }
}
}
// 创建一个实例
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 0)
}).then(value => {
console.log(value)
})
手写符合Promise/A+规范的Promise的更多相关文章
- 手写一款符合Promise/A+规范的Promise
手写一款符合Promise/A+规范的Promise 长篇预警!有点长,可以选择性观看.如果对Promise源码不是很清楚,还是推荐从头看,相信你认真从头看到尾,并且去实际操作了,肯定会有收获的.主要 ...
- 一起学习造轮子(一):从零开始写一个符合Promises/A+规范的promise
本文是一起学习造轮子系列的第一篇,本篇我们将从零开始写一个符合Promises/A+规范的promise,本系列文章将会选取一些前端比较经典的轮子进行源码分析,并且从零开始逐步实现,本系列将会学习Pr ...
- 一步一步实现一个Promise A+规范的 Promise
2015年6月,ES2015(即ES6)正式发布后受到了非常多的关注.其中很重要的一点是 Promise 被列为了正式规范. 在此之前很多库都对异步编程/回调地狱实现了类 Promise 的应对方案, ...
- 手写基于Promise A+规范的Promise
const PENDING = 'pending';//初始态const FULFILLED = 'fulfilled';//初始态const REJECTED = 'rejected';//初始态f ...
- 手写promise
写在前面: 在目前的前端分开中,我们对于异步方法的使用越来越频繁,那么如果处理异步方法的返回结果,如果优雅的进行异步处理对于一个合格的前端开发者而言就显得尤为重要,其中在面试中被问道最多的就是对Pro ...
- 手写一个Promise/A+,完美通过官方872个测试用例
前段时间我用两篇文章深入讲解了异步的概念和Event Loop的底层原理,然后还讲了一种自己实现异步的发布订阅模式: setTimeout和setImmediate到底谁先执行,本文让你彻底理解Eve ...
- 手写 Promise
在上一章节中我们了解了 Promise 的一些易错点,在这一章节中,我们会通过手写一个符合 Promise/A+ 规范的 Promise 来深入理解它,并且手写 Promise 也是一道大厂常考题,在 ...
- 手写Promise看着一篇就足够了
目录 概要 博客思路 API的特性与手写源码 构造函数 then catch Promise.resolved Promise.rejected Promise.all Promise.race 概要 ...
- 按照 Promise/A+ 规范逐行注释并实现 Promise
0. 前言 面试官:「你写个 Promise 吧.」 我:「对不起,打扰了,再见!」 现在前端越来越卷,不会手写 Promise 都不好意思面试了(手动狗头.jpg).虽然没多少人会在业务中用自己实现 ...
随机推荐
- Java——IO
[Java流式输入/输出原理]
- Java——抽象类
[抽象类] 抽象类中方法有定义的必要,但是没有实现的必要,因为需要子类进行重写.
- c++复习——临考前的女娲补天 >=.<
一些零零散散的知识点... 1.抽象类只能作为其他类的基类,不能建立对象,但抽象类的派生类如果给出纯虚函数的函数体,这个派生类仍然是一个抽象类.//这个好理解 懂了 2.抽象类不能作为参数类型,函数的 ...
- CF 696 A Lorenzo Von Matterhorn(二叉树,map)
原题链接:http://codeforces.com/contest/696/problem/A 原题描述: Lorenzo Von Matterhorn Barney lives in NYC. ...
- 730KII 打印机 Win7 2017年11月更新系统补丁后无法打印
卸载11月份编号为KB4048960的系统更新
- [CSP-S模拟测试]:购物(柯朵莉树)
题目描述 $visit_world$有一个商店,商店里卖$N$个商品,第$i$个的价格为$a[i]$我们称一个正整数$K$是美妙的,当且仅当我们可以在商店里选购若干个商品,使得价格之和落在区间$[K, ...
- matlab 重命名文件和文件夹
1.查看文件存在 dir() 若存在,返回文件信息 dir(‘test.txt’) %查看当前目录是否存在test.txt文件 dir(‘C:\test.txt’) %查看指定目录是否存在 ...
- 基于Skyline的web开发(6.x)
多窗口对比 一个页面加载多个TerraExplorer3DWindow和SGWorld等只有第一个能用(即使用iframe也是一样) 所以我决定打开两个新页面实现多窗口对比,然后我在<主页面&g ...
- OpenStack 多节点纳管 vCenter 5.5
目录 目录 测试环境 Nova 配置OpenStack 纳管 vCenter 虚拟机 Glance 配置OpenStack 纳管 vCenter 镜像 Cinder 配置OpenStack 纳管 vC ...
- 阶段1 语言基础+高级_1-3-Java语言高级_02-继承与多态_第7节 内部类_7_内部类的概念与分类
完整