当前位置: 首页 > Web前端 > HTML

JavaScript异步操作中的嵌套回调函数

时间:2023-03-28 16:36:34 HTML

嵌套回调函数常用于两种逻辑顺序的异步操作场景。考虑以下问题:我们如何顺序加载两个脚本?自然的解决方案是将第二个loadScript调用放在回调中,如下所示:loadScript('/my/script.js',function(script){alert(`Cool,${script.src}已加载,让我们加载再来一个`);loadScript('/my/script2.js',function(script){alert(`酷,第二个脚本已加载`);});});外层loadScript完成后,回调开始内层loadScript调用。如果我们想顺序加载更多脚本怎么办?loadScript('/my/script.js',function(script){loadScript('/my/script2.js',function(script){loadScript('/my/script3.js',function(script){//...在加载所有脚本后继续});});});回调参数的错误处理在上面的例子中,我们没有考虑错误。如果脚本加载失败怎么办?我们的回调应该能够对此做出反应。这是跟踪加载错误的loadScript的改进版本:functionloadScript(src,callback){letscript=document.createElement('script');脚本.src=src;script.onload=()=>回调(空,脚本);script.onerror=()=>callback(newError(`${src}`的脚本加载错误));document.head.append(script);}它在成功加载时调用callback(null,script),否则调用callback(error)。使用代码:loadScript('/my/script.js',function(error,script){if(error){//处理错误}else{//脚本加载成功}});我们使用的loadScript方法其实很常见。它被称为“错误优先回调”风格。约定是:如果发生错误,回调的第一个参数是为错误保留的。然后调用回调(错误)。第二个参数(如果需要,还有下一个参数)用于成功的结果。然后调用callback(null,result1,result2...)。因此,单个回调函数用于报告错误和返回结果。毁灭金字塔乍一看,嵌套回调函数似乎是一种可行的异步编码方式。的确。对于一两个嵌套调用,复杂度在程序员的控制范围内。但是对于一个接一个的多个异步操作,我们会有这样的代码: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{//...在加载所有脚本后继续(*)}});}});}});随着调用变得越来越嵌套,代码变得越来越深,越来越难以管理,特别是如果我们有真正的代码而不是……可能包括更多的循环、条件语句等。这有时被称为回调地狱或厄运金字塔。嵌套调用的“金字塔”随着每个异步操作向右增长。很快就失控了。我们可以将每个匿名回调函数重写为具有名称的标准函数,以部分避免回调地狱问题:loadScript('1.js',step1);functionstep1(error,script){if(error){handleError(error);}else{//...loadScript('2.js',step2);}}functionstep2(error,script){if(error){handleError(error);}别的{//。..loadScript('3.js',step3);}}functionstep3(error,script){if(error){handleError(error);}else{//...所有脚本加载完成后继续(*)}}我们使用JavaScript提供的promise,可以从根本上避免回调地狱的问题。