模拟Promise的功能,  按照下面的步骤,一步一步

1. 新建是个构造函数

2. 传入一个可执行函数 函数的入参第一个为 fullFill函数 第二个为 reject函数; 函数立即执行, 参数函数异步执行
3. 状态一旦更改就不可以变更 只能 pending => fulfilled 或者 pending => rejected
4. then 的时候要处理入参的情况 successCallback 和failCallback 均可能为非函数

  • 默认的 failCallback 一定要将异常抛出, 这样下一个promise便可将其捕获 异常冒泡的目的

5. then 中执行回调的时候要捕获异常 将其传给下一个promise

  • 如果promise状态未变更 则将回调方法添加到对应队列中
  • 如果promise状态已经变更 需要异步处理成功或者失败回调
  • 因为可能出现 回调结果和当前then返回的Promise一致 从而导致死循环问题

6. catch只是then的一种特殊的写法 方便理解和使用
7. finally 特点

  1. 不过resolve或者reject都会执行
  2. 回调没有参数
  3. 返回一个Promise 且值可以穿透到下一个then或者catch

8. Promise.resolve, Promise.reject 根据其参数返回对应的值 或者状态的Promise即可
9. Proise.all 特点

  1. 返回一个Promise
  2. 入参是数组 resolve的情况下出参也是数组 且结果顺序和调用顺序一致
  3. 所有的值或者promise都完成才能resolve 所有要计数
  4. 只要有一个为reject 返回的Promise便reject

10. Proise.race 特点

  1. 返回一个Promise
  2. 入参是数组 那么出参根据第一个成功或者失败的参数来确定
  3. 只要有一个resolve 或者reject 便更改返回Promise的状态
const PENDING = 'pending' //等待
const FULFILLED = 'fulfilled' //成功
const REJECTED = 'rejected' //失败 const fulfilledCallback = [] //成功回调函数
const rejectedCallback = [] //失败回调函数 class MyPromise { constructor (executor) { try{
executor(this.resolve, this.reject)
} catch (e){
this.reject(e)
}
} status = PENDING//promise的状态
value = undefined//成功之后的值
reason = undefined//失败之后的值
fulfilledCallback = [] //成功回调函数
rejectedCallback = [] //失败回调函数
resolve = value => {
//如果状态不是等待, 阻止程序继续往下执行
if(this.status !== PENDING){
return
}
this.status = FULFILLED
this.value = value
//判断成功回调是否存在,如果存在, 调用
// this.fulfilledCallback && this.fulfilledCallback(this.value)
while(this.fulfilledCallback.length) this.fulfilledCallback.shift()() }
reject = reason => {
//如果状态不是等待, 阻止程序继续往下执行
if(this.status !== PENDING){
return
}
this.status = REJECTED
this.reason = reason
//判断失败回调是否存在,如果存在, 调用
// this.rejectedCallback && this.rejectedCallback(this.reason)
while(this.rejectedCallback.length) this.rejectedCallback.shift()()
}
then = (fulfilledCallback, rejectedCallback) => {
fulfilledCallback = fulfilledCallback ? fulfilledCallback : value => value
rejectedCallback = rejectedCallback ? rejectedCallback : reason => {throw reason}
let promise2 = new MyPromise((resolve, reject) => { //判断状态
if(this.status === FULFILLED){
setTimeout(() => {
try {
//判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
//如果是普通值,直接调用resolve
let x = fulfilledCallback(this.value)
//外面加载完,才能获取到promise2,用异步解决
resolvePromise(promise2,x,resolve, reject)
} catch (error) {
reject(error)
} },0) }else if(this.status === REJECTED){ setTimeout(() => {
try {
//判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
//如果是普通值,直接调用resolve
let x = rejectedCallback(this.reason)
//外面加载完,才能获取到promise2,用异步解决
resolvePromise(promise2,x,resolve, reject)
} catch (error) {
reject(error)
} },0)
}else{
//等待状态
this.fulfilledCallback.push(() => {
setTimeout(() => {
try {
//判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
//如果是普通值,直接调用resolve
let x = fulfilledCallback(this.value)
//外面加载完,才能获取到promise2,用异步解决
resolvePromise(promise2,x,resolve, reject)
} catch (error) {
reject(error)
} },0)
});
this.rejectedCallback.push(() => {
setTimeout(() => {
try {
//判断x 传过来的可能是promise,先查看promise返回的结果,在决定是用resolve还是reject,
//如果是普通值,直接调用resolve
let x = rejectedCallback(this.reason)
//外面加载完,才能获取到promise2,用异步解决
resolvePromise(promise2,x,resolve, reject)
} catch (error) {
reject(error)
} },0)
});
}
})
return promise2
} static all (array) {
let result= []
let index = 0; return new MyPromise((resolve, reject) => { function addData (key, value) {
result[key] = value
index++
if (index === array.length) {
resolve(result)
}
} for (let i = 0; i < array.length; i++) { if (array[i] instanceof MyPromise) {
//promise对象
array[i].then(value => addData(i, value), reason => reject(reason))
} else {
//普通值, 放到数组里
addData(i, array[i])
}
}
}) } static resolve (value) {
if(value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value)) } finally (callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.resolve(callback()).then(() => {throw reason})
}) } catch (rejectedCallback) {
return this.then(undefined, rejectedCallback)
} } function resolvePromise(promise2,x,resolve, reject){ if(x === promise2){
return reject(new TypeError('啦啦啦啦'))
}
if(x instanceof MyPromise){
//是promise
//往下直接传
x.then(resolve,reject)
}else{
//普通值
resolve(x)
}
} module.exports = MyPromise;

模拟Promise的功能的更多相关文章

  1. Java基础面试操作题:线程同步代码块 两个客户往一个银行存钱,每人存三十次一次存一百。 模拟银行存钱功能,时时银行现金数。

    package com.swift; public class Bank_Customer_Test { public static void main(String[] args) { /* * 两 ...

  2. ListView模拟微信好友功能

    ListView模拟微信好友功能 效果图: 分析: 1.创建listView 2.创建数据 3.创建适配器 将数据放到呈现数据的容器里面. 将这个容器(带数据)连接适配器. 其实是直接在我们自己写的a ...

  3. 编写函数模拟strcpy()函数功能

    strcpy(字符数组1,字符串2) strcpy( )用于将字符串2复制到字符数组1中 /* strcpy(字符数组1,字符串2) strcpy( )用于将字符串2复制到字符数组1中 模拟strcp ...

  4. TCP模拟QQ聊天功能

    需求: 模拟qq聊天功能:实现客户端与服务器(一对一)的聊天功能,客户端首先发起聊天,输入的内容在服务器端和客户端显示,然后服务器端也可以输入信息,同样信息在客户端和服务端显示. 提示: 客户端 1) ...

  5. 标准IO的简单应用,动静态库,读取系统时间并打印,模拟ls -l功能

    2015.2.27星期五,小雨 标准IO实现的复制功能: #include <stdio.h>#include <errno.h> #define N 64 int main( ...

  6. js模拟实现继承功能

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  7. 简单模拟 Promise

    class promise { constructor(fn) { this.data = null; this.err = null; this.isPromise = false; this.er ...

  8. 在VFP6中模拟CursorAdapter的功能

    这个是我在2002年做的一个VFP程序中实现的方法, 现在看来功能和VFP8,9中的CursorAdapter非常相似, 因为属性设置有许多相同的地方,我甚至怀疑CA就是就是在这样的基础上再包装出来的 ...

  9. 模拟storage copy 功能失败的记录

    试验设想: 机器1: alter database begin backup 然后,在oracle仍然活动的状态下,将$ORACLE_BASE目录全部压缩拷贝到机器2 机器2: startup:失败 ...

  10. PyQt4 模拟记事本基本功能(保存,打开文件)

    完成功能: 1. 默认[保存]按钮enable 2. 修改文本的内容后,[enable] 3. 解决字符乱码问题:utf-8 4. 提示:如果修改了文件没有保存的时候,又尝试打开新的文件,给出相关的提 ...

随机推荐

  1. 《Markdown常用语法及快捷键》

    Markdown常用语法及快捷键       [```]+空格--代码格式 [---]+空格--水平分割线 [&emsp]+[;]--空格 [shift]+[tab]--清除当前行的格式

  2. Windows安装Jenkins详细教程(图文教程)

    一.安装前准备 1.提前安装好jdk,可参考以下链接进行安装 Windows安装JDK详细教程(图文教程) 2.Jenkins官网下载安装包(因为本人jdk安装的是1.8,所以会和最新版jenkins ...

  3. display:block 和display:inline-block的区别和用法

    1).块状元素:(div,p,form,ul,ol,li) ,独占一行,默认情况width为100% 2).行内块状元素:(span,img,a),不会独占一行,相邻的元素一直排在同一行,排满了才会换 ...

  4. Leetcode刷题笔记(双指针)

    1.何为双指针 双指针主要用来遍历数组,两个指针指向不同的元素,从而协同完成任务.我们也可以类比这个概念,推广到多个数组的多个指针. 若两个指针指向同一数组,遍历方向相同且不会相交,可以称之为滑动窗口 ...

  5. 用户输入学号,如果是以aabcddef开头,并且后边是4位数字,前两位大于06小于等于当前年份。判断用户输入是否合法

    package seven_topic; import java.util.*; public class p_19_1 { public static void main(String[] args ...

  6. 【.NET 6+Loki+Grafana】实现轻量级日志可视化服务功能

    前言:日志功能是几乎所有程序或系统都必备的一个功能.该文章通过使用Loki+Grafana来实现日志记录与可视化查询,欢迎围观. 有关环境: 操作系统:WIN 10 .NET环境:.NET 6 开发环 ...

  7. Explain:你见过这样的Sql吗?

    上一篇我们讲到Mysql索引底层逻辑,为了了解后续sql知识,我们还是需要先学习一下相关"工具"得使用 一.Explain介绍 EXPLAIN是MySQl必不可少的一个分析工具,主 ...

  8. 【C++】从零开始的CS:GO逆向分析3——写出一个透视

    [C++]从零开始的CS:GO逆向分析3--写出一个透视 本篇内容包括: 1. 透视实现的方法介绍 2. 通过进程名获取进程id和进程句柄 3. 通过进程id获取进程中的模块信息(模块大小,模块地址, ...

  9. 2022-08-20-nas寄了就搞网络__网络升级计划_(估计又得白给)

    layout: post cid: 13 title: nas寄了就搞网络? 网络升级计划 (估计又得白给) slug: 13 date: 2022/08/20 16:31:00 updated: 2 ...

  10. (Java初学篇)IDEA项目新建流程和软件配置优化以及怎么彻底删除项目

    相信很多小伙伴们在初学 Java 时都会出现这样的情况,就是在网上一顿搜索加捣鼓终于把 JDK 和IDEA 这两款软件安装配置好,但是发现面对这个陌生的软件此时却无从下手,那么接下来我就给大家简单地介 ...