80 lines
4.0 KiB
Markdown
80 lines
4.0 KiB
Markdown
---
|
||
title: Callback Functions
|
||
localeTitle: 回调函数
|
||
---
|
||
本文简要介绍了Javascript编程语言中回调函数的概念和用法。
|
||
|
||
## 功能是对象
|
||
|
||
我们需要知道的第一件事是在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`调用与上面的示例具有相同的结果:
|
||
|
||
```javascript
|
||
createQuote("eat your vegetables!", function(quote){
|
||
console.log(quote);
|
||
});
|
||
```
|
||
|
||
顺便说一句,你_不必_用“回拨”作为参数的名称,使用Javascript只需要知道它是正确的参数名称。基于上面的例子,下面的函数将以完全相同的方式运行。
|
||
|
||
```javascript
|
||
function createQuote(quote, functionToCall) {
|
||
var myQuote = "Like I always say, " + quote;
|
||
functionToCall(myQuote);
|
||
}
|
||
```
|
||
|
||
## 为什么要使用Callbacks?
|
||
|
||
大多数时候,我们正在创建以**同步**方式运行的程序和应用程序。换句话说,我们的一些操作只有在前面的操作完成后才会启动。通常,当我们从其他来源(例如外部API)请求数据时,我们并不总是知道_何时_会回送我们的数据。在这些情况下,我们希望等待响应,但我们并不总是希望我们的整个应用程序在获取数据时停止运行。这些情况是回调函数派上用场的地方。
|
||
|
||
我们来看一个模拟对服务器的请求的示例:
|
||
|
||
```javascript
|
||
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`函数调用的匿名函数参数也是一个回调函数!因此,示例的原始回调实际上是由另一个回调执行的。如果你可以帮忙的话,小心不要嵌套太多的回调,因为这会导致一种叫做“回调地狱”的东西!顾名思义,处理起来并不是一种乐趣。 |