回调函数
2021 javascript回调函数是将一个函数作为参数传递给另一个函数,当外部函数被调用的时候可以执行一些回调函数。
function funcA() {
console.log('funcA');
}
function funcB(callback) {
console.log('funcB');
callback();
}
funcB(funcA);
匿名回调函数
function funcB(function() {
// ...
})
回调函数的作用
首先使用一个不使用回调函数的例子:
const calc = function(num1, num2, calcType) {
if (calcType === 'add') {
return num1 + num2;
} else if (calcType === 'multiply') {
return num1 * num2;
}
};
calc(2, 3, 'add'); // 5
calc(2, 3, 'multiply'); // 6
接下来使用回调函数:
const add = function(a, b) {
return a + b;
}
const multiply = function(a, b) {
return a * b;
}
const calc = function(num1, num2, callback) {
return callback(num1, num2);
}
calc(2, 3, add); // 5
calc(2, 3, multiply); // 6
回调地狱
回调函数的第一个问题就是回调地狱的问题,回调地狱就是回调函数的大量嵌套回调或者链式回调。
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})
回调地狱不仅带来阅读代码的困难性,包含了大量的嵌套与缩进和各个交错的执行顺序。同时回调函数的脆弱性,一旦指定了顺序和事件,代码会变得异常复杂,难以维护。
信任问题
回调函数的另一个问题就是信任问题。
如上述例子中:
calc(2, '3', add); // 23
如上结果,并不是我们预期的结果。对于回调函数 add 我们可以改进
function add(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw Error('Bad parameters');
}
return a + b;
}
参考链接
- MDN: callback function
- Wiki: Callback (computer programming)
- 知乎:回调函数(callback)是什么?
- callbackhell
- 《你不知道的Javascript(中)》 第2章