论Promise在前端江湖的地位及作用

系列文章:

  1. 先撸清楚:并发/并行、单线程/多线程、同步/异步
  2. 论Promise在前端江湖的地位及作用
  3. 少年,且听我细说 EventLoop/宏任务/微任务是咋玩的?

前言

上篇文章阐述了并发/并行、单线程/多线程、同步/异步等概念,这篇将会分析Promise的江湖地位。
通过本篇文章,你将了解到:

  1. 为什么需要回调?
  2. 什么是回调地狱?
  3. Promise解决了什么问题?
  4. Promise常用的API
  5. async和await 如影随形
  6. Promise的江湖地位

1. 为什么需要回调?

1.1 同步回调

先看个简单的Demo:

function add(a: number, b: number) {
   
   
    return a + b
}

function reprocess(a: number) {
   
   
    return a * a
}

function calculate() {
   
   
    //加法运算
    let sum = add(4, 5)
    //进行再处理
    let result = reprocess(sum)
    //输出最终结果
    console.log("result:", result)
}

先进行加法运算,再对运算的结果进行处理,最终输出结果。
在reprocess()函数里我们对结果进行了平方,现在想要对它进行除法操作,那么依葫芦画瓢,需要再定义一个函数:

function reprocess2(a: number) {
   
   
    return a / 2
}

再后来,还需要继续增加其它功能如减法、乘法、取模等运算,那不是要新增不少函数吗?
假设该模块的主要功能是进行加法,至于对加法结果的再加工它并不关心,外界调用者想怎么玩就怎么玩。于是,回调出现了。
我们重新设计一下代码:

//新增函数作为入参
function add(a: number, b: number, callbackFun: (sum: number) => number) {
   
   
    let sum = a + b
    return callbackFun(sum)
}

function calculate() {
   
   
    //加法运算
    let result = add(4, 5, (sum) => {
   
   
        return sum / sum
    })
    //输出最终结果
    console.log("result:", result)

    let result2 = add(6, 8, (sum) => {
   
   
        return sum * sum - sum / 2
    })
    //输出最终结果
    console.log("result2:", result2)
}

add()函数最后一个入参是函数类型的参数,调用者需要实现这个函数,我们称这个函数为回调函数。于是在calculate()函数里,我们可以针对不同的需求调用add()函数,并通过回调函数实现不同的数据加工逻辑。

calculate()函数和回调函数是在同一线程里执行,并且按照代码书写的先后顺序执行,此时的回调函数是同步回调

1.2 异步回调

假若add()函数里对数据的加工需要一定的时间,我们用setTimeout模拟一下耗时操作:

//新增函数作为入参
function add(a: number, b: number, callbackFun: (sum: number) => void) {
   
   
    setTimeout(() => {
   
   
        let sum = a + b
        callbackFun(sum)
    })
}

function calculate() {
   
   
    //加法运算
    add(4, 5, (sum) => {
   
   
        let result = sum / sum
        //输出最终结果
        console.log("result:", result)//第1个打印
    })
    console.log("calculate end...")//第2个打印
}

从打印结果看,第2个打印反而比第一个打印先出现,说明第二个打印语句先执行。
calculate()函数执行add()函数的时候,并没有一直等待回调的结果,而是立马执行了第二个打印语句,而当add()函数内部实现执行时,才会执行回调函数,虽然calculate()和回调函数在同一线程执行,但是它们并没有按照代码书写的先后顺序执行,此时的回调函数是异步回调

1.3 为什么需要它?

回调函数的出现使得代码设计更灵活。
你可能会说:异步回调我还可以理解,毕竟或多或少都会涉及到异步调用,但同步回调不是脱裤子放屁吗?
其实不然,同步回调更多的表现在灵活度上,比如我们遍历一个数组:

const score = [60, 70, 80, 90, 100]
score.forEach((value, index, array) => {
   
   
    console.log("value:", value, " index:", index)
})

forEach()函数接收的是一个同步回调函数,该函数里可以获取到数组里每一个值,并可以对它进行自定义的逻辑操作。
除了forEach()函数,同步回调还大量地被运用于其它场景。

2. 什么是回调地狱?

先看一段代码:

interface NetCallback {
   
   
    //错误返回
    error: (errMsg: string) => void
    //成功返回
    succeed: (data: object) => void
}

function fetchNetData(url: string, netCallback: NetCallback) {
   
   
    //模拟网络耗时
    setTimeout(() => {
   
   
        if (Math.random() > 0.2) {
   
   
            //成功
            netCallback.succeed({
   
   code: 200, msg: 'success'})
        } else 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值