关于前端:JavaScript-异步操作里的嵌套回调函数

44次阅读

共计 2082 个字符,预计需要花费 6 分钟才能阅读完成。

嵌套回调函数常常用在两个逻辑上具备先后顺序的异步操作场景中。

思考上面的问题:咱们如何按程序加载两个脚本?

天然的解决方案是将第二个 loadScript 调用放在回调中,如下所示:

loadScript('/my/script.js', function(script) {alert(`Cool, the ${script.src} is loaded, let's load one more`);

  loadScript('/my/script2.js', function(script) {alert(`Cool, the second script is loaded`);
  });

});

外层 loadScript 实现后,回调启动内层的 loadScript 调用。

如果咱们想要程序加载更多的脚本,该怎么办?

loadScript('/my/script.js', function(script) {loadScript('/my/script2.js', function(script) {loadScript('/my/script3.js', function(script) {// ...continue after all scripts are loaded});

  });

});

对于回调参数的出错解决

在下面的例子中,咱们没有思考谬误。如果脚本加载失败怎么办?咱们的回调应该可能对此做出反馈。

这是一个改良的 loadScript 版本,能够跟踪加载谬误:

function loadScript(src, callback) {let script = document.createElement('script');
  script.src = src;

  script.onload = () => callback(null, script);
  script.onerror = () => callback(new Error(`Script load error for ${src}`));

  document.head.append(script);
}

它调用 callback(null, script) 胜利加载,否则调用 callback(error)。

生产代码:

loadScript('/my/script.js', function(error, script) {if (error) {// handle error} else {// script loaded successfully}
});

咱们用于 loadScript 的办法实际上很常见。它被称为“谬误优先回调(error-first callback)”格调。

约定是:

如果产生谬误,回调的第一个参数是为谬误保留的。而后回调(谬误)被调用。

第二个参数(如果须要,还有下一个参数)用于胜利的后果。而后调用 callback(null, result1, result2…)。

因而,单个回调函数用于报告谬误和传回后果。

Pyramid of Doom

乍一看,嵌套回调函数看起来像是一种可行的异步编码方法。的确如此。对于一个或两个嵌套调用,其复杂度尚在编程人员可能掌控的范畴内。

然而对于一个接一个的多个异步操作,咱们会有这样的代码:

loadScript('1.js', function(error, script) {if (error) {handleError(error);
  } else {
    // ...
    loadScript('2.js', function(error, script) {if (error) {handleError(error);
      } else {
        // ...
        loadScript('3.js', function(error, script) {if (error) {handleError(error);
          } else {// ...continue after all scripts are loaded (*)
          }
        });

      }
    });
  }
});

随着调用变得更加嵌套,代码变得更深并且越来越难以治理,特地是如果咱们有真正的代码而不是 …… 可能包含更多的循环、条件语句等。

这有时被称为 回调天堂 末日金字塔

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

咱们能够把每个匿名回调函数,改写成为由名称的规范函数,来局部水平的躲避回调天堂问题:

loadScript('1.js', step1);

function step1(error, script) {if (error) {handleError(error);
  } else {
    // ...
    loadScript('2.js', step2);
  }
}

function step2(error, script) {if (error) {handleError(error);
  } else {
    // ...
    loadScript('3.js', step3);
  }
}

function step3(error, script) {if (error) {handleError(error);
  } else {// ...continue after all scripts are loaded (*)
  }
}

咱们应用 JavaScript 提供的 promise,能够从根本上躲避回调天堂问题。

正文完
 0