让前端飞Web前端之路饥人谷技术博客

实现一个简易Promise

2019-10-09  本文已影响0人  大春春

前言

Promise是老生常谈的问题,作为ES6时代新出的针对异步编程的一种解决方案,它解决了之前由各种setTimeout或者各种callback函数所造成的回调地狱, 最大的作用就是换了种写法,使得回调不再横向发展,改成了竖向发展 ,当然代码更好看更好理解也就能够提高生产效率(目前已经有async/await,可以使得代码组织能力和可读性更加高了),那么今天就来看看Promise的原理,以及如何实现一个简易的Promise吧。

Promise要解决什么问题

在Promise出现之前,js代码中充斥着各种回调地狱(特别是在node中,由于err一般作为回调的第一个参数,结果导致需要层层判断),例如下面的代码:

image.png
这就导致一个问题,代码横向发展成一个金字塔状,而可读性也会随着回调函数的增加变得越来越差,这就被称为回调地狱。
当然了,我们可以通过针对代码进行一些优化,例如抽离逻辑函数等,增强代码的可读性,从而解决回调地狱的问题,但是想法是想法,现实中有可能会因为deadline逼近,需求频繁变更等原因导致根本没时间或者没精力去优化代码,所以回调地狱的问题依旧非常严重。
对此,ES6推出了Promise A/+规范用于解决该问题,现代浏览器中的Promise对象就是根据该规范的实现。

Promise是如何解决回调地狱的

上面所说的回调地狱是横向发展的逻辑金字塔,Promise的使用可以将其改造成竖向的逻辑流,例如下面两段代码的对比:

old:
ajax(url, () => {
    // 处理逻辑
    ajax(url1, () => {
        // 处理逻辑
        ajax(url2, () => {
            // 处理逻辑
            ajax(url3, () => {
                // 处理逻辑
            })
        })
    })
})

new:
ajax(url)
    .then(res => {
        // 逻辑处理
        return ajax(url1)
    })
    .then(res => {
        // 逻辑处理
        return ajax(url2)
    })
    .then(res => {
        return ajax(url3)
    })

由此也可以得出,Promise有两大有点:

  1. 减少缩进
  2. 解决类似if(err)形式的代码

Promise的简易实现

  1. resolve的时候,Promise内部的状态就变为了fulfilled,且只能从pending状态变为fulfilled:
    image.png
  2. 因为在callbacks中存储的回调都是只能在Promise接收到的函数的其他事务处理完毕后才进行处理,所以这里对callbacks里的回调进行调用时候需要使用异步调用,可以使用setTimeout(因为setTimeout是宏任务,所以可能产生一些其他问题,但是在这里可以使用它来暂时模拟),在node中可以使用process.nextTick:
    image.png

我们可以对现在完成的代码进行测试:

  1. 使用官方Promise:
    image.png
  2. 使用自己实现的Promise:
    image.png

同理,我们reject的处理方式也可以采用这种方式:

image.png
上一篇下一篇

猜你喜欢

热点阅读