一、背景
在JavaScript的学习中,回调函数一直是比较令人头疼的东西,回调也是编写和处理 JavaScript 程序异步逻辑的最常用方式。简单来说,当把一个函数作为参数传递给另外一个函数,那么这个函数就称为一个回调函数,比如说定时器回调,事件监听回调等等。而且回调一定会产生闭包,使用回调函数实际上就是在使用闭包。现在需要来正式了解一下回调,并对他有一定的认识。
二、回调函数的特点
之前说了,回调函数一般是作为函数的参数来使用,实际上我们进行函数声明的时候,可以传递很多参数,其中这些参数是不是函数并不是绝对的,因为JS是弱类型语言,一般要运行时才知道具体变量类型。当这些个形参中有些是我们定义好了的,他就是个回调函数,并且在特定时机下,我们会去调用他,比如:
function test(callback) {
setTimeout(() => {
callback('return something...');
}, 3000);
}
那么我们在使用这个函数的时候就需要传递一个回调函数作为参数,这个回调函数,在一个特定的时机会被调用,也就是定时器3s后等待事件循环过程轮到他后,去调用这个函数。而我们就可以在这儿定义函数的参数,拿到实际的数据,比如:
test((data) => {
console.log(data);
})
总的来说,回调函数需要在一个被调用的环境中被定义和调用,然后在使用的时候传入实际函数,就可以得到传入的数据,然后我们就可以对这些数据做一些特定处理。
三、简单应用
我们一定要把握住回调函数的特点,并应用好他,这样可以在某种情况下,使我们的代码更规范,也更好理解和使用,比如:
function request(method, url, params, resolve, reject) {
let ajax;
if(XMLHttpRequest) {
ajax = new XMLHttpRequest();
} else {
ajax = new ActiveXObject('Microsoft.XMLHTTP');
}
ajax.open(method, url, true);
ajax.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
ajax.send(params);
ajax.onreadystatechange = function () {
if(ajax.readyState == 4 && ajax.status == 200) {
let res = ajax.responseText; // 这里一定要先把数据保存到一个变量中,然后再传给回调函数,否则无法取值。
resolve(res);
}
}
}
如上定义了一个简单地使用原生XHR实现的封装的一个网络请求工具,我们在使用的时候只需要这样:
// 这是在菜鸟网站测试的,如果在别的地方会有跨域问题。
request('GET', 'https://www.runoob.com/try/ajax/ajax_info.txt', null, (data) => {
console.log(data);
})
那么我们在使用的时候就可以以一种更好的方式处理数据。
总之,回调函数有好也有坏,不好好利用的话,可能产生回调地狱,使得代码读起来非常困难。但同时好好利用回调函数,我们可以实现非常强大的功能,比如Promise。