回调函数解决异步代码
说到回调函数大家在平时肯定是经常使用的,例如我要加载一个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)”风格。既
callback
的第一个参数是为 error 而保留的。一旦出现 error,callback(err)
就会被调用。- 第二个参数(和下一个参数,如果需要的话)用于成功的结果。此时
callback(null, result1, result2…)
就会被调用。
回调函数导致回调地狱
使用回调方式的方法去处理异步编程是可行的,但是如果嵌套了多个异步代码时会导致代码层次变得更深,维护难度也随之增加,被称为“回调地狱”或“厄运金字塔”
这类代码的出现往往会让代码变得不再那么好维护,那么如何去解决回调地狱的问题呢?Promise可以解决回调地狱的问题