一、 是什么
回调函数是一个函数,它被作为参数传递给另一个函数(通常称为“主调函数”或“高层函数”)。当主调函数完成某些操作或满足特定条件后,它会调用这个回调函数。
// 定义一个回调函数
const callback=()=> {
console.log('回调函数被调用了!');
}
// 定义一个主调函数,它接受一个回调函数作为参数
const a=(callback)=> {
// 主调函数执行一些逻辑
console.log('主调函数开始执行...');
// 假设这里有一些异步操作或条件判断
// 当主调函数完成逻辑后,它调用回调函数
callback();
}
// 调用主调函数,并将回调函数作为参数传递
a(callback);
二、使用场景
- 异步操作:当某个操作需要花费很长时间才能完成(例如网络请求、文件读写等)时,我们通常不希望主线程等待这个操作完成。相反,我们会立即返回并在操作完成时调用一个回调函数。
- 事件监听:在GUI编程中,当某个事件(如按钮点击)发生时,我们通常希望执行某个函数。这个函数就是一个回调函数,它会在事件发生时被调用。
- 定时器:在JavaScript中,
setTimeout
和setInterval
函数都接受一个回调函数作为参数,这个回调函数会在指定的时间后或在每个指定的时间间隔后被调用。 - 高阶函数:在函数式编程中,函数可以作为参数传递给其他函数,也可以作为其他函数的返回值。当作为参数的函数被调用时,它实际上就是一个回调函数。
三、回调地狱
回调地狱(Callback Hell)是指在编程中,由于多个回调函数嵌套调用,导致代码可读性差、维护困难的情况,例如
// 假设有三个操作,每个操作都需要依赖于前一个操作的结果
const Operation1 = (callback) => {
setTimeout(() => {
const result1 = "1";
callback(null, result1);
}, 1000);
};
const Operation2 = (result1, callback) => {
setTimeout(() => {
const result2 = `${result1},2`;
callback(null, result2);
}, 1000);
};
const Operation3 = (result2, callback) => {
setTimeout(() => {
const result3 = `${result2},3`;
callback(null, result3);
}, 1000);
};
// 回调地狱示例
Operation1((err, result1) => {
if (err) {
console.error("Error1:", err);
return;
}
Operation2(result1, (err, result2) => {
if (err) {
console.error("Error2:", err);
return;
}
Operation3(result2, (err, result3) => {
if (err) {
console.error("Error3:", err);
return;
}
console.log("Final Result:", result3);//Final Result: 1,2,3
});
});
});
解决方式:
使用promise
const Operation1 = () =>
new Promise(resolve => {
setTimeout(() => {
const result1 = "1";
resolve(result1);
}, 1000);
});
const Operation2 = (result1) =>
new Promise(resolve => {
setTimeout(() => {
const result2 = `${result1},2`;
resolve(result2);
}, 1000);
});
const Operation3 = (result2) =>
new Promise(resolve => {
setTimeout(() => {
const result3 = `${result2},3`;
resolve(result3);
}, 1000);
});
使用async/await
const sequenceOperations=async()=> {
try {
const result1 = await Operation1();
const result2 = await Operation2(result1);
const result3 = await Operation3(result2);
console.log("Final Result:", result3); // Final Result: 1,2,3
} catch (error) {
console.error("An error occurred:", error);
}
}