回调金字塔是什么意思_面试官:介绍下回调

介绍:回调函数

JavaScript主机环境提供了许多函数,允许您调度异步操作。换句话说,我们现在开始的行动,但它们会在稍后结束。

例如,setTimeout函数就是这样一个函数。

在现实世界中还有其他异步操作的例子,例如加载脚本和模块(我们将在后面的章节中介绍)。

看看loadScript(src)函数,它用给定的src加载脚本:

它将用给定的src动态创建的新标记添加到文档中。浏览器自动开始加载,并在完成时执行。

我们可以这样使用这个函数:

脚本是“异步”执行的,因为它现在开始加载,但是在函数已经完成之后运行。

如果在loadScript(…)下面有任何代码,它不会等到脚本加载完成。

假设我们需要在新脚本加载后立即使用它。它声明了新的函数,我们想要运行它们。

但如果我们在调用loadScript(…)之后立即这样做,那就行不通了:

406/5000当然,浏览器可能没有时间加载脚本。到目前为止,loadScript函数还没有提供跟踪加载完成情况的方法。脚本加载并最终运行,仅此而已。但是我们想知道它什么时候发生,从脚本中使用新的函数和变量。

让我们添加一个回调函数作为loadScript的第二个参数,它应该在脚本加载时执行:

现在,如果我们想从脚本中调用新函数,我们应该把它写入回调函数中:

这就是它的思想:第二个参数是一个在操作完成时运行的函数(通常是匿名的)。

下面是一个带有真实脚本的可运行的示例:

这就是所谓的“基于回调”的异步编程风格。一个异步执行的函数应该提供一个回调参数,在函数完成后,我们把它放在这里运行。

这里我们是在loadScript中做的,当然这是一种一般的方法。

回调中的回调

我们如何按顺序加载两个脚本:第一个,然后是第二个?

自然的解决方案是将第二个loadScript调用放在回调函数中,像这样:

外部loadScript完成后,回调将启动内部loadScript。

如果我们还想要一个脚本呢?

每个新动作都在回调中。这对于很少的操作来说很好,但是对于很多操作来说就不好了,所以我们将很快看到其他的变体。

错误处理

在上面的例子中,我们没有考虑错误。如果脚本加载失败怎么办?我们的回调应该能够对此做出反应。

这是一个改进版的loadScript,可以跟踪加载错误:

它调用callback(null, script)来成功加载,否则调用callback(error)。

用法:

再说一次,我们用于loadScript的配方实际上很常见。它被称为" error-first callback "样式。

惯例是:

回调函数的第一个参数保留给发生错误时使用。然后调用callback(err)。

第二个参数(如果需要,还有下一个参数)用于成功的结果。然后调用callback(null, result1, result2…)。

因此,一个回调函数既用于报告错误,也用于传回结果。

回调地狱

乍一看,这是一种可行的异步编码方式。的确如此。对于一个或两个嵌套调用,它看起来很好。

但是对于一个接一个的多个异步动作,我们会有这样的代码:

在上述代码中:

我们加载1.js,然后,如果没有错误。

我们加载2.js,然后,如果没有错误。

我们加载3.js,然后如果没有错误-做其他事情(*)。

随着调用越来越嵌套,代码变得越来越深,越来越难以管理,特别是如果我们有真正的代码而不是……这可能包括更多的循环、条件语句等等。

这有时被称为"回调地狱"或"末日金字塔"

嵌套调用的“金字塔”随着每个异步操作向右增长。很快它就失控了。

所以这种编码方式不是很好。

我们可以通过将每个操作都变成独立的函数来缓解这个问题,如下所示:

看到了吗?它做的是一样的,现在没有深度嵌套,因为我们将每个操作都设置为单独的顶级函数。

它可以工作,但代码看起来像一个撕裂的电子表格。它很难阅读,你可能会注意到人们在阅读时需要在各篇文章之间来回切换。这很不方便,特别是如果读者不熟悉代码,不知道眼睛往哪里跳。

同样,名为step*的函数都是单一用途,它们只是为了避免“毁灭金字塔”而创建的。“没有人会在行动链之外再使用它们。这里有点命名空间混乱。

(我们想要更好的。)

幸运的是,还有其他方法可以避免这样的金字塔。最好的方法之一是使用“承诺”,这将在下一章中描述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值