源码地址

  1. 先看基本使用

    const promise = new Promise((resolve, reject) => {
    resolve(value)
    // or reject(reason)
    })

    创建Promise时传入的回调函数是立即执行的,所以我们的Promise应该是这样(用ts实现)

    function BDuckPromise(fn: (resolve: (value: any) => void, reject: (reason: any) => void) => any) {
    
      function resolve(value: any) {
    
      }
    
      function reject(reason: any) {
    
      }
    
      fn(resolve, reject);
    
    }
  2. 每个Promise对象都有三种生命状态:PENDING(未开始)、FULFILLED(已完成)、REJECTED(已失败)。生命状态只能是PENDING => FULFILLED 或者 PENDING => REJECTED 且一旦发生改变不可逆转。此时我们的代码是这样,具有了状态。

    enum STATE {
    PENDING = 0,
    FULFILLED = 1,
    REJECTED = 2
    } function BDuckPromise(fn: (resolve:(value: any) => void, reject: (reason: any) => void) => any) {
    let store = null,
    state = STATE.PENDING function resolve(value: any): void {
    store = value;
    state = STATE.FULFILLED;
    } function reject(reason: any): void {
    store = reason;
    state = STATE.REJECTED;
    } fn(resolve, reject)
    }
  3. 一个Promise对象回调中传入的值(value)或者拒因(reason)是在该示例对象的then函数中获取的

    promise.then(value => {
    console.log(value);
    return value + 1
    }, reason => {
    // ....
    })

    then具有两个回调函数onfulfilled(用于成功时传递value)、onrejected(用于失败时传递reason)

    所以我们then方法大概是长这样子

    function BDuckPromise() {
    this.then = (onfulfilled, onrejected) => {
    if(state === STATE.PENDING) {
    return
    } if(state === STATE.FULFILLED) {
    onfulfilled(store)
    return
    } if(state === STATE.REJECTED) {
    onrejected(store)
    return
    }
    }
    }

    但是等一下,如果我们写成这个样子当我们调用then的时候就必须要求promise的状态已经发生过改变我们才能获取到value或者reason,这个显然不是我们需要的。但是我们应该要写成什么样呢?分析一下

    当我们调用then时候promise仍然处于pending状态时,我们应该怎么将value或者reason在它状态发生改变是传递出去呢?

    显然,我们应该在状态发生改变时调用对应的onfulfilled或者onrejected回调。

    那么我们就应该在状态为pending时将回调函数都存储起来,一旦状态改变了,就调用这些回调函数,这下就清楚了,应当在resolve或者reject中调用我们的onfulfilled或者onrejected回调

    enum STATE {
    PENDING = 0,
    FULFILLED = 1,
    REJECTED = 2
    } function BDuckPromise(fn: (resolve:(value: any) => void, reject: (reason: any) => void) => any) {
    let store = null,
    state = STATE.PENDING,
    callbacks = []; function resolve(value: any): void {
    store = value;
    state = STATE.FULFILLED;
    callbacks.forEach(callback => {
    if(callback.onfulfilled && 'function' === typeof callback.onfulfilled) {
    callback.onfulfilled(store)
    }
    });
    callbacks = null
    }; function reject(reason: any): void {
    store = reason;
    state = STATE.REJECTED;
    callbacks.forEach(callback => {
    if(callback.onrejected && 'function' === typeof callback.onrejected) {
    callback.onrejected(store)
    }
    });
    callbacks = null
    }; this.then = (onfulfilled, onrejected) => {
    if(state === STATE.PENDING) {
    callbacks.push({
    onfulfilled,
    onrejected
    })
    return
    } if(state === STATE.FULFILLED) {
    onfulfilled(store)
    return
    } if(state === STATE.REJECTED) {
    onrejected(store)
    return
    }
    };
    fn(resolve, reject)
    }
  4. then函数是有返回值的,且返回的的是一个新的Promise对象,所以还得改=_=!

    const promise1 = new Promise((resolve, reject) => {
    resolve(1)
    })
    // promise2 是一个新的Promise对象
    const promise2 = promise1.then(value => {
    return value + 1
    })

    现在改成这样子

    this.then = (onfulfilled, onrejected) => {
    return new BDuckPromise((_resolve, _reject) => {
    if(state === STATE.PENDING) {
    callbacks.push({
    onfulfilled,
    onrejected
    })
    return
    } if(state === STATE.FULFILLED) {
    onfulfilled(store)
    return
    } if(state === STATE.REJECTED) {
    onrejected(store)
    return
    }
    });
    }
  5. 上一个then函数中return的值会传递给下一个then中作为值

    const promise1 = new Promise((resolve, reject) => {
    resolve(1)
    })
    // promise2 是一个新的Promise对象
    const promise2 = promise1.then(value => {
    return value + 1
    })
    .then(value => {
    console.log(value) // 2
    })

    好吧,接着改=_=

    this.then = (onfulfilled, onrejected) => {
    return new BDuckPromise((_resolve, _reject) => {
    if(state === STATE.PENDING) {
    callbacks.push({
    onfulfilled,
    onrejected,
    _resolve,
    _reject
    })
    return
    } if(state === STATE.FULFILLED) {
    const ret = onfulfilled(store)
    _resolve(ret)
    return
    } if(state === STATE.REJECTED) {
    const ret = onrejected(store)
    _reject(ret)
    return
    }
    });
    } // 相应的resolve, reject也做相应的更改
    function resolve(value: any): void {
    store = value;
    state = STATE.FULFILLED;
    callbacks.forEach(callback => {
    if(callback.onfulfilled && 'function' === typeof callback.onfulfilled) {
    const ret = callback.onfulfilled(store)
    callback._resolve(ret)
    }
    })
    } function reject(reason: any): void {
    store = reason;
    state = STATE.REJECTED;
    callbacks.forEach(callback => {
    if(callback.onrejected && 'function' === typeof callback.onrejected) {
    const ret = callback.onrejected(store)
    callback._reject(ret)
    }
    })
    }
  6. 如果then中return的是一个新的Promise则下一个then中的value或reason是这个返回的Promise中resolve或者reject中传递value或者reason

    enum STATE {
    PENDING = 0,
    FULFILLED = 1,
    REJECTED = 2
    } function BDuckPromise(fn: (resolve:(value: any) => void, reject: (reason: any) => void) => any) {
    let store:any = null,
    state = STATE.PENDING,
    callbacks:any = [] function resolve(value: any): void {
    setTimeout(() => {
    state = STATE.FULFILLED;
    // value 是一个Promise对象
    if(value && 'object' === typeof value && value.then && 'function' === typeof value.then) {
    // do then
    value.then(resolve, reject)
    return
    }
    // value 不是Promise对象
    store = value;
    callbacks.forEach(callback => {
    if(callback.onfulfilled && 'function' === typeof callback.onfulfilled) {
    const ret = callback.onfulfilled(store)
    callback._resolve(ret)
    }
    })
    callbacks = []
    })
    } function reject(reason: any): void {
    setTimeout(() => {
    state = STATE.REJECTED;
    // value 是一个Promise对象
    if(reason && 'object' === typeof reason && reason.then && 'function' === typeof reason.then) {
    reason.then(resolve, reject)
    return
    }
    // value 不是Promise对象
    store = reason;
    callbacks.forEach(callback => {
    if(callback.onrejected && 'function' === typeof callback.onrejected) {
    const ret = callback.onrejected(store)
    callback._reject(ret)
    }
    })
    callbacks = []
    }, 0)
    } this.then = (onfulfilled, onrejected) => {
    return new BDuckPromise((_resolve, _reject) => {
    if(state === STATE.PENDING) {
    callbacks.push({
    onfulfilled,
    onrejected,
    _resolve,
    _reject
    })
    return
    } if(state === STATE.FULFILLED) {
    const ret = onfulfilled(store)
    _resolve(ret)
    return
    } if(state === STATE.REJECTED) {
    const ret = onrejected(store)
    _reject(ret)
    return
    }
    });
    } fn(resolve, reject)
    }
    export default BDuckPromise;

还有reject的处理,目前是不合规范的

大概就是这样,不搞了

自己实现一个Promise库的更多相关文章

  1. 小而美的Promise库——promiz源码浅析

    背景 在上一篇博客[[译]前端基础知识储备--Promise/A+规范](https://segmentfault.com/a/11...,我们介绍了Promise/A+规范的具体条目.在本文中,我们 ...

  2. 一步一步实现基于Task的Promise库(一)Promise的基本实现

    如果我们现在有一个需求,大概是先读取一个文件的内容,再把得到的内容传给后台去解析,最后把解析后的结果再保存到那个文件,按照最原始的做法代码就是下面这个样子的: //读取文件的原始内容 var read ...

  3. Promise原理讲解 && 实现一个Promise对象 (遵循Promise/A+规范)

    1.什么是Promise? Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一 2.对于几种常见异步编程方案 回调函数 事件监听 发布/ ...

  4. node.js的Promise库-bluebird示例

    前两天公司一哥们写了一段node.js代码发给我,后面特意提了一句“写的不太优雅”.我知道,他意思是回调嵌套回调,因为当时比较急也就没有再纠结.然而内心中总记得要解决这个问题.解决node.js的回调 ...

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

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

  6. 基于PromiseA+规范实现一个promise

    实现如果下规范的promise Aplus规范 1,promise是一个类:有三个状态 pending/等待态 fulfilled/成功态 rejected/失败态 2,promise默认执行器立即执 ...

  7. 【转载】写一个js库需要怎样的知识储备和技术程度?

    作者:小爝链接:https://www.zhihu.com/question/30274750/answer/118846177来源:知乎著作权归作者所有,转载请联系作者获得授权. 1,如何编写健壮的 ...

  8. 创建你的第一个JavaScript库

    是否曾对Mootools的魔力感到惊奇?是否有想知道Dojo如何做到那样的?是否对jQuery感到好奇?在这个教程中,我们将了解它们背后的东西并且动手创建一个超级简单的你最喜欢的库. 我们其乎每天都在 ...

  9. 教你一步一步实现一个Promise

    Promise我想现在大家都非常熟悉了,主要作用就是解决异步回调问题,这里简单介绍下. Promise规范是CommonJS规范之一,而Promise规范又分了好多种,比如 Promises/A.Pr ...

随机推荐

  1. C# 实体集合和实体转换成相应的string、XDocument、XElement、XDocument

    https://msdn.microsoft.com/zh-cn/library/system.xml.linq.xelement(v=vs.110).aspx XElement.Parse 方法 ( ...

  2. 【phpstorm】破解安装

    1.使用前修改C:\windows\system32\Driver\hosts文件,将“0.0.0.0 account.jetbrains.com”添加到hosts文件中. 2. 浏览器打开 http ...

  3. Linux-软件包管理-rpm命令管理-安装-卸载

    mount 确认光盘是否挂载 mount /dev/cdrom /mnt/cdrom 将设备名称/dev/cdrom安装到/mnt/cdrom挂载点下面 mount 查看光盘是否已经挂载 (ro表示只 ...

  4. 随笔小问题(一)--mac打开class文件

    本来不想写这个东西的.但是这个却费了我一番周折. 我要先声明一点的是,我从来不讲iOS当成一个单独的系统,而是将这个操作系统归位unix内核的系统. 简单来说,我把它当成linux在用. 但是,mac ...

  5. Spring boot 配置 swagger

    1.maven配置包 <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --> <dep ...

  6. unity, 替换shader渲染(Rendering with Replaced Shaders)

    实现特效,尤其是一些后处理特效,经常需要将各物体的shader替换为另一套shader进行渲染到纹理,再后再进行合成或以某种叠加方式叠加到最后的画面上去. 再复杂一点儿的,可能不同的物体所用的替换sh ...

  7. 如何在iOS上实现对HTTPS的支持(转)

    原文地址:http://blog.5ibc.net/p/101504.html 首先,需要明确你使用HTTP/HTTPS的用途,因为OSX和iOS平台提供了多种API,来支持不同的用途,官方文档< ...

  8. 基于js白色简洁样式计算器

    今天给大家分享一款白色简洁样式计算器JS代码是一款精美简洁计算器JS代码插件网页特效,软件应用,后台应用JS计算器插件代码免费下载.适用浏览器:360.FireFox.Chrome.Safari.Op ...

  9. 复现IIS6.0远程命令执行漏洞

    出这个漏洞有一定时间了,一直没测试,因为知道这个漏洞有条件的,好吧,顺便感谢royal大佬今天晚上日内网的指点. 漏洞要求: 开启Webdav PS:不想刚拿下的内网服务器一下权限掉了,又不想放xx远 ...

  10. 用swift开发仪表盘控件(二)

    二.代码分析 这个控件本质就是从UIView继承的一个类而已.所以整个代码事实上就是一个定制的UIView类. 依据UIView的规则进行例如以下初始化: required init(coder aD ...