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. es6的扩展运算符

    扩展运算符用三个点号表示,功能是把数组或类数组对象展开成一系列用逗号隔开的值,扩展运算符有几点作用: 一,展开数组 //展开数组 let a = [1,2,3,4,5], b = [...a,6,7] ...

  2. vue-cli目录结构介绍

    一个vue-cli的项目结构如下: 文件结构细分: 1.build——[webpack配置] build文件主要是webpack的配置,主要启动文件是dev-server.js,当我们输入npm ru ...

  3. 快速获取批量处理Docker镜像SQL语句

    .获取批量pull语句 select concat('docker pull develop-harbor.geostar.com.cn/', t.name, ':', t1.tag) name fr ...

  4. 嵌入式Linux文件系统知多少

    Nand/Nor Flash 在嵌入式Linux产品中,通常使用的存储介质为Nand Flash和Nor Flash,而手机.相机等产品通常使用eMMC.SD Card作为存储介质,导致这种差异的原因 ...

  5. day48—JavaScript键盘事件

    转行学开发,代码100天——2018-05-03 今天继续学习JavaScript事件基础之键盘事件. 键盘代号获取 keyCode 键盘事件:onkeydown onkeyup 如通过键盘上下左右按 ...

  6. delphi自定义事件处理

    http://www.cnblogs.com/ywangzi/archive/2012/09/06/2673414.html delphi自定义事件处理   为什么我们点击按钮,就会执行按钮的oncl ...

  7. tensorflow 关于 矩阵 运算 + 符号得含义。 2维 数组 + 1纬数组, 就是每一行都 加一边 1纬数组。 呵呵

    小锋子Shawn(403568338)  13:51:23mnist.training.images?墨须(964489899)  13:51:27我的图片是100*100的,该怎么兼容.  小锋子S ...

  8. Spring学习03——AOP Demo

    切面类StudentServiceAspect.java package com.su.advice; import org.aspectj.lang.JoinPoint; import org.as ...

  9. 【MM系列】SAP MM-模块物料主数据简介

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MM-模块物料主数据简介   ...

  10. LeetCode——141 设计链表

    题目: 简单说下思路: 用两个指针,一个跑得快,一个跑得慢(例如一个每次前进两步,一个前进一步),这样只要快指针不会撞上NULL(如果遇到了NULL的情况那么必然不存在环),快指针肯定会和慢指针碰面( ...