手写符合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).虽然没多少人会在业务中用自己实现 ...
随机推荐
- ExoPlayer + 边缓存边播放
在此基础上改动:https://www.cnblogs.com/candyzhmm/p/9957928.html private void openPlayer(String videoUrl) { ...
- CF1051F The Shortest Statement Dijkstra + 性质分析
动态询问连通图任意两点间最短路,单次询问. 显然,肯定有一些巧妙地性质(不然你就发明了新的最短路算法了233)有一点很奇怪:边数最多只比点数多 $20$ 个,那么就可以将这个图看作是一个生成树,上面连 ...
- 【l转】VS2015下解决:无法解析的外部符号 __imp___vsnprintf 及__iob_func
https://blog.csdn.net/hebbely/article/details/53780562
- PowerDesigner相关总结
1.PowerDesigner 工具生成数据库Report指导 摘自:https://www.cnblogs.com/zycblog/archive/2010/05/11/1732918.html 1 ...
- Linux驱动开发6——DDR内存分配
1.kmalloc和kfree #include <linux/slab.h> void *kmalloc(size_t size, int flags); flag: GFP_ATOMI ...
- .net 4.5 Test Async Task 异步测试
using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using Syst ...
- DelayQueue 源码分析
DelayQueue DelayQueue 是基于 PriorityQueue 实现的线程安全的无界优先级阻塞队列, 队列的头部元素必须在超时后才能移除,元素必须实现 Delayed 接口. 创建实例 ...
- python 2和3 字符编码
在字符编码问题上,python2 和python3 还是有点不同的.今日写篇博客,彻底理清这个问题.. 字符编码问题的由来: 这要从计算发展历史来看待这个问题了,一开始,歪果仁使用ASCII码,8位( ...
- android hidl
1.定义.hal接口文件,如: 在vendor/sprd/interface中新建目录hello,其中定义好hidl接口,如: package vendor.sprd.hardware.hello@1 ...
- 007-elasticsearch5.4.3【一】概述、Elasticsearch 访问方式、Elasticsearch 面向文档、常用概念
一.概述 Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上. Elasticsearch 也是使用 Java 编写的,它的内部使用 L ...