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的更多相关文章

  1. 手写一款符合Promise/A+规范的Promise

    手写一款符合Promise/A+规范的Promise 长篇预警!有点长,可以选择性观看.如果对Promise源码不是很清楚,还是推荐从头看,相信你认真从头看到尾,并且去实际操作了,肯定会有收获的.主要 ...

  2. 一起学习造轮子(一):从零开始写一个符合Promises/A+规范的promise

    本文是一起学习造轮子系列的第一篇,本篇我们将从零开始写一个符合Promises/A+规范的promise,本系列文章将会选取一些前端比较经典的轮子进行源码分析,并且从零开始逐步实现,本系列将会学习Pr ...

  3. 一步一步实现一个Promise A+规范的 Promise

    2015年6月,ES2015(即ES6)正式发布后受到了非常多的关注.其中很重要的一点是 Promise 被列为了正式规范. 在此之前很多库都对异步编程/回调地狱实现了类 Promise 的应对方案, ...

  4. 手写基于Promise A+规范的Promise

    const PENDING = 'pending';//初始态const FULFILLED = 'fulfilled';//初始态const REJECTED = 'rejected';//初始态f ...

  5. 手写promise

    写在前面: 在目前的前端分开中,我们对于异步方法的使用越来越频繁,那么如果处理异步方法的返回结果,如果优雅的进行异步处理对于一个合格的前端开发者而言就显得尤为重要,其中在面试中被问道最多的就是对Pro ...

  6. 手写一个Promise/A+,完美通过官方872个测试用例

    前段时间我用两篇文章深入讲解了异步的概念和Event Loop的底层原理,然后还讲了一种自己实现异步的发布订阅模式: setTimeout和setImmediate到底谁先执行,本文让你彻底理解Eve ...

  7. 手写 Promise

    在上一章节中我们了解了 Promise 的一些易错点,在这一章节中,我们会通过手写一个符合 Promise/A+ 规范的 Promise 来深入理解它,并且手写 Promise 也是一道大厂常考题,在 ...

  8. 手写Promise看着一篇就足够了

    目录 概要 博客思路 API的特性与手写源码 构造函数 then catch Promise.resolved Promise.rejected Promise.all Promise.race 概要 ...

  9. 按照 Promise/A+ 规范逐行注释并实现 Promise

    0. 前言 面试官:「你写个 Promise 吧.」 我:「对不起,打扰了,再见!」 现在前端越来越卷,不会手写 Promise 都不好意思面试了(手动狗头.jpg).虽然没多少人会在业务中用自己实现 ...

随机推荐

  1. Java——JDK1.5新增强的for循环

    <1>JDK1.5新增的for循环对于遍历array或collection非常便利. <2>缺陷:        数组:不能方便地访问下标值.        集合:与使用Int ...

  2. CodeForces 1198C 1199E Matching vs Independent Set

    Time limit 1000 ms Memory limit 262144 kB 这题是一场cf里,div1的第三题,div2的第5题 中文题意 给一张无向图,没说连通性,要你选出一个大小为n的匹配 ...

  3. Educational Codeforces Round 16 D. Two Arithmetic Progressions (不互质中国剩余定理)

    Two Arithmetic Progressions 题目链接: http://codeforces.com/contest/710/problem/D Description You are gi ...

  4. [CSP-S模拟测试]:矩阵游戏(数学)

    题目描述 $LZK$发明一个矩阵游戏,大家一起来玩玩吧,有一个$N$行$M$列的矩阵.第一行的数字是$1,2,...,M$,第二行的数字是$M+1,M+2,...,2\times M$,以此类推,第$ ...

  5. 阿里云万网虚拟主机安装配置Https(SSL)教程

    太多太多的用户咨询阿里云虚拟主机是否可以安装SSL数字证书?万网空间是否可以支持HTTPS协议访问网站?答案只有一个:目前阿里云虚拟主机都不支持安装SSL证书!但是,但是,可以曲线实现目标! 1.为了 ...

  6. 【转】GLSL资料收集

    https://blog.csdn.net/u013467442/article/details/44457869 其中入门资料相当好:https://blog.csdn.net/racehorse/ ...

  7. vi不能使用jk 映射?

    vi不能使用jk 映射? 因为vi 不支持inormap 这种键映射! 要安装vim-enhanced后才能使用vim命令, 也才能够使用 键映射!

  8. Retrofit RestAdapter 配置说明

    RestAdapter.Builder builder = new RestAdapter.Builder();                    builder.setEndpoint(ip地址 ...

  9. Powershell 音乐播放

    目录 目录 前言 systemwindowsmediamediaplayer 前言 Powershell抱着.NET的大腿,与生俱来了许多非常便捷的功能.例如--音乐的自动播放 system.wind ...

  10. WPF与DevExpress之——实现类似于安装程序下一步下一步的样式窗体

    话不多说先上图  点击下一步  跳转到第二页  项目准备: 1.DevExpress 19/18/17(三个版本都可以) 2.Vs2019 3..Net framework>4.0 项目结构: ...