freeCodeCamp/guide/chinese/javascript/callback-functions/index.md

4.0 KiB
Raw Blame History

title localeTitle
Callback Functions 回调函数

本文简要介绍了Javascript编程语言中回调函数的概念和用法。

功能是对象

我们需要知道的第一件事是在Javascript中函数是一流的对象。因此我们可以像处理其他对象一样使用它们比如将它们分配给变量并将它们作为参数传递给其他函数。这很重要因为后一种技术允许我们在应用程序中扩展功能。

回调函数

回调函数是_作为参数_传递给另一个函数的函数以便稍后“回调”。接受其他函数作为参数的函数称为高阶函数 它包含回调函数执行_时_的逻辑。这两者的结合使我们能够扩展我们的功能。

为了说明回调,让我们从一个简单的例子开始:

function createQuote(quote, callback){ 
  var myQuote = "Like I always say, " + quote; 
  callback(myQuote); // 2 
 } 
 
 function logQuote(quote){ 
  console.log(quote); 
 } 
 
 createQuote("eat your vegetables!", logQuote); // 1 
 
 // Result in console: 
 // Like I always say, eat your vegetables! 

在上面的例子中, createQuote是高阶函数,它接受两个参数,第二个是回调。 logQuote函数用于传入我们的回调函数。当我们执行createQuote函数_1时_ 请注意当我们将它作为参数传递时我们_不会将_括号_附加_到logQuote 。这是因为我们不想立即执行我们的回调函数,我们只是想将函数定义传递给高阶函数,以便以后执行。

此外我们需要确保如果我们传入的回调函数需要参数那么我们在执行回调时提供这些参数_2_ 。在上面的例子中,那将是callback(myQuote);声明,因为我们知道logQuote需要传入引号。

另外,我们可以传递匿名函数作为回调。以下对createQuote调用与上面的示例具有相同的结果:

createQuote("eat your vegetables!", function(quote){ 
  console.log(quote); 
 }); 

顺便说一句你_不必_用“回拨”作为参数的名称使用Javascript只需要知道它是正确的参数名称。基于上面的例子下面的函数将以完全相同的方式运行。

function createQuote(quote, functionToCall) { 
  var myQuote = "Like I always say, " + quote; 
  functionToCall(myQuote); 
 } 

为什么要使用Callbacks

大多数时候,我们正在创建以同步方式运行的程序和应用程序。换句话说我们的一些操作只有在前面的操作完成后才会启动。通常当我们从其他来源例如外部API请求数据时我们并不总是知道_何时_会回送我们的数据。在这些情况下我们希望等待响应但我们并不总是希望我们的整个应用程序在获取数据时停止运行。这些情况是回调函数派上用场的地方。

我们来看一个模拟对服务器的请求的示例:

function serverRequest(query, callback){ 
  setTimeout(function(){ 
    var response = query + "full!"; 
    callback(response); 
  },5000); 
 } 
 
 function getResults(results){ 
  console.log("Response from the server: " + results); 
 } 
 
 serverRequest("The glass is half ", getResults); 
 
 // Result in console after 5 second delay: 
 // Response from the server: The glass is half full! 

在上面的示例中我们向服务器发出模拟请求。经过5秒后响应被修改然后我们的回调函数getResults被执行。要查看此操作,您可以将上述代码复制/粘贴到浏览器的开发人员工具中并执行它。

此外,如果您已经熟悉setTimeout ,那么您一直在使用回调函数。传递给上面例子的setTimeout函数调用的匿名函数参数也是一个回调函数!因此,示例的原始回调实际上是由另一个回调执行的。如果你可以帮忙的话,小心不要嵌套太多的回调,因为这会导致一种叫做“回调地狱”的东西!顾名思义,处理起来并不是一种乐趣。