什么是回调地狱?

61 阅读2分钟

回调函数解决异步代码

说到回调函数大家在平时肯定是经常使用的,例如我要加载一个js文件并使用这个js文件中的方法,代码是这样子的

function loadScript (src) {
    const script = document.createElement('script'); 
    script.src = src; 
    document.head.append(script);
}

loadScript('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js')
console.log(_) // undefined

这样子去加载lodash中的方法,是不能成功获取的,原因是:script标签加载js文件是异步的,是需要时间的,我们可以改写一下这个方法,把加载成功的回调暴露出去

function loadScript (src, callback) {
    const script = document.createElement('script'); 
    script.src = src;
    script.onload = () => callback(script)
    document.head.append(script);
}

loadScript('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js', () => { console.log(_) //ok })

通过传递回调函数的方式就可以成功获取到script加载的js对象,还可以再改造一下这个函数,把加载失败的方法也通过回调函数的方式传递出去

function loadScript (src, callback) {
    const script = document.createElement('script'); 
    script.src = src;
    script.onload = () => callback(script)
    script.onerror = () => callback(new Error(`Script load error for ${src}`))
    document.head.append(script);
}
loadScript('/my/script.js', (error, script) => { 
    if (error) { // 处理 error } 
    else { // 脚本加载成功 } 
  });

这种回调函数的风格叫做“Error 优先回调(error-first callback)”风格。既

  1. callback 的第一个参数是为 error 而保留的。一旦出现 error,callback(err) 就会被调用。
  2. 第二个参数(和下一个参数,如果需要的话)用于成功的结果。此时 callback(null, result1, result2…) 就会被调用。

回调函数导致回调地狱

使用回调方式的方法去处理异步编程是可行的,但是如果嵌套了多个异步代码时会导致代码层次变得更深,维护难度也随之增加,被称为“回调地狱”或“厄运金字塔” image.png

这类代码的出现往往会让代码变得不再那么好维护,那么如何去解决回调地狱的问题呢?Promise可以解决回调地狱的问题