# 回调函数

3 min read
Table of Contents

回调函数是将一个函数作为参数传递给另一个函数,当外部函数被调用的时候可以执行一些回调函数。

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
}

参考链接


More Posts