模拟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. G&GH01 注册/安装/设置

    注意事项与声明 平台: Windows 10 作者: JamesNULLiu 邮箱: jamesnulliu@outlook.com 博客: https://www.cnblogs.com/james ...

  2. Python数据科学手册-Pandas:向量化字符串操作、时间序列

    向量化字符串操作 Series 和 Index对象 的str属性. 可以正确的处理缺失值 方法列表 正则表达式. Method Description match() Call re.match() ...

  3. phpoffice文档笔记

    目录 phpword html转word phpexcel 从数据库导出 phpword html转word <?php namespace app\index\controller; use ...

  4. firewalld教程

    修改配置 cat firewalld.conf | grep -Ev "^#|^$" DefaultZone=trusted #主要是这个位置,必须修改trusted的 Minim ...

  5. yaml文件执行后常见错误解决

    yaml文件中个别数值有大写,报错信息如下 : The Deployment "my-nginx" is invalid: spec.template.spec.volumes[0 ...

  6. R语言、02 案例2-1 Pelican商店、《商务与经济统计》案例题

    编程教材 <R语言实战·第2版>Robert I. Kabacoff 课程教材<商务与经济统计·原书第13版> (安德森) P48.案例2-1 Pelican 商店 PS C: ...

  7. Python中dataclass库

    目录 dataclass语法 一. 简介 二. 装饰器参数 三. 数据属性 1. 参数 2. 使用示例 3. 注意事项 四. 其他 1. 常用函数 2. 继承 3. 总结 dataclass语法 一. ...

  8. 适合生产制造企业用的ERP系统有哪些?

    什么叫适合?匹配很重要!同是生产制造企业,规模不同.行业不同.发展阶段不同.生产模式不同.管理理念不同,适用的ERP自然也不同.不同规模的企业选用不同的系统,如过你是大型企业,业务管理都比较标准规范, ...

  9. 追求性能极致:Redis6.0的多线程模型

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...

  10. PHP + ELK实现日志记录

    一个简单的PHP 文件 效果 full.conf文件 流程: 开启logstash服务之后. 在业务代码里面操作函数写入日志.log logstash通过实践戳获取到用户的变更,取出最后一行数据,发送 ...