在学习JavaScript时,不会花很长时间,直到遇到回调。 这些对于初学者来说可能看起来很奇怪和神秘,但是了解它们的工作方式以利用语言的力量非常重要。 在本文中,我将使用易于理解的示例来教您回调的基础。
什么是回叫?
简而言之:回调是要在另一个函数(通常是异步的)完成执行之后执行的函数-因此称为“回调”。
更复杂地说:在JavaScript中,函数是对象。 因此,函数可以将函数作为参数,并且可以由其他函数返回。 执行此操作的函数称为高阶函数。 作为参数传递并随后由接收该参数的函数调用的任何函数都称为回调函数。
好多话。 让我们看一些例子,以进一步说明这一点。
本文最初在codeburst.io上发布,并在得到作者许可的情况下在此处重新发布。 如果您喜欢阅读,何不去那里看看Brandon的其他文章呢? 如果您想全面提高JavaScript技能,为什么不前往SitePoint Premium并注册我们的JavaScript入门课程 。
为什么我们需要回调?
出于一个非常重要的原因-JavaScript是一种事件驱动语言。 这意味着JavaScript不会继续等待响应,而是会在侦听其他事件时继续执行。 让我们看一个基本的例子:
function first(){
console.log(1);
}
function second(){
console.log(2);
}
first();
second();
如您所料,首先执行函数,然后执行第二函数,将以下内容记录到控制台:
// 1
// 2
到目前为止一切都很好。
但是,如果函数首先包含某种无法立即执行的代码怎么办? 例如,我们必须先发送请求然后等待响应的API请求? 为了模拟此动作,将使用setTimeout
,它是一种本机JavaScript方法,在指定的延迟后调用一个函数。 我们将函数延迟500毫秒以模拟API请求。 我们的新代码将如下所示:
function first(){
// Simulate a code delay
setTimeout( function(){
console.log(1);
}, 500 );
}
function second(){
console.log(2);
}
first();
second();
理解setTimeout()
现在如何工作并不重要(尽管如果您很好奇,我们有关于该主题的教程 )。 重要的是您看到我们已经移动了console.log(1);
在我们的500毫秒延迟内。 那么,当我们调用函数时会发生什么呢?
first();
second();
// 2
// 1
即使我们先调用了first()
函数,我们在second()
函数之后也注销了该函数的结果。
这并不是说JavaScript没有按照我们想要的顺序执行我们的函数,而是JavaScript在继续执行second()之前没有等待first()
的响应。
那为什么给你看这个呢? 因为您不能只是一个接一个地调用函数,并希望它们以正确的顺序执行。 回调是一种确保某些代码在其他代码已经完成执行之前不会执行的方法。
建立回呼
好了,足够多的讨论,让我们创建一个回调!
首先,打开浏览器开发者控制台(您可以通过在Windows / Linux上按Ctrl + Shift + J或在Mac上按Cmd + Option + J来执行此操作)。 然后在控制台中键入以下函数声明:
function doHomework(subject) {
alert(`Starting my ${subject} homework.`);
}
上面,我们创建了函数doHomework
。 我们的函数采用一个变量,即我们正在研究的主题。 通过在控制台中键入以下命令来调用函数:
doHomework('math');
// Alerts: Starting my math homework.
现在让我们添加回调-作为doHomework()
函数中的最后一个参数,我们可以传入回调。 然后在对doHomework()
调用的第二个参数中定义回调函数。
function doHomework(subject, callback) {
alert(`Starting my ${subject} homework.`);
callback();
}
doHomework('math', function() {
alert('Finished my homework');
});
在JS Bin上尝试此示例
如您所见,如果您在控制台中键入上述代码,则会收到两个背对背的警报:“正在开始作业”警报,然后是“已完成作业”警报。
但是,并非总是必须在我们的函数调用中定义回调函数。 它们可以在我们的代码的其他地方定义,如下所示:
function doHomework(subject, callback) {
alert(`Starting my ${subject} homework.`);
callback();
}
function alertFinished(){
alert('Finished my homework');
}
doHomework('math', alertFinished);
在JS Bin上尝试以下示例:
什么是JavaScript中的回调? 在jsbin.com上
此示例的结果与前面的示例完全相同,但是设置略有不同。 如您所见,在doHomework()
函数调用期间,我们已将alertFinished
函数定义作为参数传递!
真实的例子
上周,我发表了一篇有关如何用38行代码创建Twitter机器人的文章。 该文章中的代码起作用的唯一原因是因为Twitter的API。 向API发出请求时,必须等待响应,然后才能对该响应采取行动。 这是真实的回调用例的绝佳示例。 请求如下所示:
T.get('search/tweets', params, function(err, data, response) {
if(!err){
// This is where the magic will happen
} else {
console.log(err);
}
});
-
T.get
仅表示我们正在向Twitter发出GET请求。 - 此请求中包含三个参数:
'search/tweets'
,这是我们的请求的路由,params
是我们的搜索参数,然后是一个匿名函数,它是我们的回调。
回调在这里很重要,因为我们需要等待服务器的响应才能继续执行代码。 我们不知道我们的API请求是否会成功,因此在通过GET请求将参数发送到search/tweets
,我们等待。 Twitter响应后,将调用我们的回调函数。 Twitter会向我们发送err
(错误)对象或response
对象。 在回调函数中,我们可以使用if()
语句来确定我们的请求是否成功,然后对新数据采取相应措施。
你做到了
干得好! 现在,您可以了解什么是回调及其如何操作。 但这仅仅是回调的冰山一角,还有很多东西要学习! 如果您有任何问题或意见,我们很高兴在下面的评论部分中听到他们的意见。