JavaScript中的回调函数(callback)

article/2025/9/17 12:02:22

前言

callback,大家都知道是回调函数的意思。如果让你举些callback的例子,我相信你可以举出一堆。但callback的概念你知道吗?你自己在实际应用中能不能合理利用回调实现功能? 我们在平时的学习中容易犯不去深究的病,功能实现了也就不再去追其原由,对一些概念模模糊糊。如果对callback没有一个清楚的理解,估计你在学习Node.js后会崩溃,因为callback是Node.js三大核心之一。

一、回调函数

回调函数的概念

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.

以上是Google的解释,非常清晰简明,小编令人窒息的四级英语水平都能看懂。
下面给一个回调的例子

function doSomething(msg, callback){//callback只是一个参数名而已,可以叫任意名alert(msg);if(typeof callback == "function"){ callback();}
} 
doSomething("回调函数", function(){alert("匿名函数实现回调!");
}); 

我们再来看几个经典的回调函数代码,我保证你一定用过他们:

回调函数例子.png

从上面的例子,我们可以看出回调与同步、异步并没有直接的联系,回调只是一种实现方式,既可以有同步回调,也可以有异步回调,还可以有事件处理回调和延迟函数回调,这些在我们工作中有很多的使用场景。


二、把使用this对象的函数作为回调函数(陷阱)

当回调函数是一个使用this对象的函数时,我们必须改变执行回调函数的调用对象来保证this对象的上下文。在讲这个问题之前,我们必须先了解JS于this的指向。我们这里不详细谈这个问题,我直接说下自己学习过程总结的判断this指向的两条经验(既然是自己的经验,那就不一定对,希望大家指正):
(1)this的指向是在函数执行的时候确定的,在函数定义的时候是确定不了,实际上this的最终指向的是那个调用它的对象
(2)调用执行函数时,“.”前面是什么,this就是什么。前面没有对象,就是window了。

回到使用this对象的函数作为回调函数这个问题,我们首先来看看下面这段代码:

//定义一个拥有一些属性和一个方法的对象 
//我们接着将会把方法作为回调函数传递给另一个函数
var clientData = {id: 096545,fullName: "Not Set",//setUsrName是一个在clientData对象中的方法setUserName: function (firstName, lastName){this.fullName = firstName + " " + lastName;}
} function getUserInput(firstName, lastName, callback){//code .....//调用回调函数存储callback(firstName, lastName);
}getUserInput("Barack","Obama",clientData.setUserName);
console.log(clientData.fullName);  //Not Set
console.log(window.fullName);  //Barack Obama
//结论:谁是主调函数,this就是指向谁

在上面的代码中,当clientData.setUsername被执行时,this.fullName并没有设置clientData对象中的fullName属性。相反,它将设置window对象中的fullName属性,这是因为callback中的this指向window的缘故。

使用Call和Apply函数来改变this指向

我们可以使用Call或者Apply函数来解决上面你的问题。到目前为止,我们知道了每个Javascript中的函数都有两个方法:Call 和 Apply。这些方法被用来设置函数内部的this对象以及给此函数传递变量
这里我们演示Apply函数实现,Call函数类似。(call接收的第一个参数为被用来在函数内部当做this的对象传递给函数的参数被挨个传递Apply函数的第一个参数也是在函数内部作为this的对象,然而最后一个参数确是传递给函数的值的数组

Apply函数:

//注意到我们增加了新的参数作为回调对象,叫做“callbackObj”
function getUserInput(firstName, lastName, callback ,callbackObj){//code .....callback.apply(callbackObj, [firstName, lastName]);
}getUserInput("Barack", "Obama", clientData.setUserName, clientData);
console.log(clientData.fullName); //Barack Obama

使用Apply函数正确设置了this对象,我们现在正确的执行了callback并在clientData对象中正确设置了fullName属性


三、回调函数是实现异步编程的利器

在程序运行中,当某些请求过程漫长,我们有时没必要选择等待请求完成继续处理下一个任务,这时使用回调函数进行异步处理可以大大提高程序执行效率。例如:AJAX请求。若是使用回调函数进行处理,代码就可以继续进行其他任务,而无需空等。实际开发中,经常在javascript中使用异步调用!
下面有个使用AJAX加载XML文件的示例,并且使用了call()函数,在请求对象(requested object)上下文中调用回调函数。

function fn(url, callback){var httpRequest;    //创建XHRhttpRequest = window.XMLHttpRequest ? new XMLHttpRequest() :   //针对IE进行功能性检测window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : undefined;httpRequest.onreadystatechange = function(){if(httpRequest.readystate === 4 && httpRequest.status === 200){  //状态判断callback.call(httpRequest.responseXML); }};httpRequest.open("GET", url);httpRequest.send();
}fn("text.xml", function(){    //调用函数console.log(this);          //此语句后输出
});console.log("this will run before the above callback.");  //此语句先输出

我们请求异步处理,意味着我们开始请求时,就告诉它们完成之时调用我们的函数。在实际情况中,onreadystatechange事件处理程序还得考虑请求失败的情况,这里我们是假设xml文件存在并且能被浏览器成功加载。这个例子中,异步函数分配给了onreadystatechange事件,因此不会立刻执行。
最终,第二个console.log语句先执行,因为回调函数直到请求完成才执行。

在Javascript编程中回调函数经常以几种方式被使用,尤其是在现代web应用开发以及库和框架中:

  • 异步调用(例如读取文件,进行HTTP请求,动态加载js文件,加载iframe资源后,图片加载完成执行回调等等)
  • 事件监听器/处理器
  • setTimeout和setInterval方法
  • 一般情况:精简代码

4.“回调地狱”问题以及解决方案

这么多回调嵌套,我还没遇到过。下面内容是直接从网上copy过来,大家看下,还是很好理解的。
在执行异步代码时,无论以什么顺序简单的执行代码,经常情况会变成许多层级的回调函数堆积以致代码变成下面的情形。这些杂乱无章的代码叫做回调地狱,因为回调太多而使看懂代码变得非常困难。我从node-mongodb-native,一个适用于Node.js的MongoDB驱动中拿来了一个例子。这段位于下方的代码将会充分说明回调地狱:

var p_client = new Db('integration_tests_20', new Server("127.0.0.1", 27017, {}), {'pk':CustomPKFactory});p_client.open(function(err, p_client) {p_client.dropDatabase(function(err, done) {p_client.createCollection('test_custom_key', function(err, collection) {collection.insert({'a':1}, function(err, docs) {collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}, function(err, cursor) {cursor.toArray(function(err, items) {test.assertEquals(1, items.length);// Let's close the dbp_client.close();});});});});});});

你应该不想在你的代码中遇到这样的问题,当你当你遇到了-你将会是不是的遇到这种情况-这里有关于这个问题的两种解决方案。

  • 给你的函数命名并传递它们的名字作为回调函数,而不是主函数的参数中定义匿名函数。
  • 模块化:将你的代码分隔到模块中,这样你就可以导出一块代码来完成特定的工作。然后你可以在你的巨型应用中导入模块。

http://chatgpt.dhexx.cn/article/HtjFCvoe.shtml

相关文章

scrapy.Request callback不执行

上一篇博客介绍了Scrapy Post Request payload数据的问题,本篇记录一下scrapy.Request callback不执行的问题。 1、大家都说的解决方式,虽然没有解决我的问题,但是还是写到这里,算是一个总结: 1.在scrapy.Request方法里…

UVM: callback机制 uvm_callback和uvm_callbacks

callback机制 callback机制提高代码的可重用性,还用于构建异常的测试用例。 广义的callback机制有post_randomize(),pre_body(),post_body(), pre_do(), mid_do()等,它们提供了额外的接口给用户。 原理 以在driver中提供callback函数接口为…

SV和UVM的Callback例程

文章目录 前言一、SystemVerilog Callback例程二、UVM Callback例程总结 前言 记录SV和UVM的两个callback的例程,方便以后用的时候进行查阅。 一、SystemVerilog Callback例程 二、UVM Callback例程 总结 记录SV和UVM的callback例程。

ajax中的callback,ajax callback是什么

ajax的callback是什么? callback是ajax中的回调函数,是在服务器对一个请求对象作出响应时调用的函数。浏览器会在某个时刻”回调”这个函数,根据5种返回状态的情况处理ajax请求结果。 callback回调函数怎么理解? 想弄明白回调函数,首先的清楚地明白函数的规则。在javascri…

通俗易懂的讲解回调函数,保证让你看懂callback

什么是回调函数?相信很多人都似懂非懂,半懂不懂,今天就通俗易懂的讲解回调函数,让你能理解回调函数的大部分作用及意义。 目录 定义 形象的例子 代码解释 用处及完整代码例子 定义 先上常规的定义: 回调函数也是…

callback(回调函数)

先讲点题外话。 编程分为两类:系统编程(system programming)和应用编程(application programming)。所谓系统编程,简单来说,就是编写库;而应用编程就是利用写好的各种库来编写具某种…

Callback回调函数介绍(C语言)

目录 1. 回调函数的定义 2. 为什么要用回调函数 3. 怎么用回调函数 3.1 怎么使用没有参数的回调函数 3.2 怎么使用带参数的回调函数 1. 回调函数的定义 最近在工作中经常用到回调函数callback,总结一下。 先来看看维基百科对callback的解释:In co…

Callback函数详解

http://shiwawa.blog.hexun.com/9925417_d.html 一,回调函数 我们经常在C++设计时通过使用回调函数可以使有些应用(如定时器事件回调处理、用回调函数记录某操作进度等)变得非常方便和符合逻辑,那么它的内在机制如何呢,怎么定义呢?它和其它函数(比如钩子函数)有何不同呢…

《软件质量保证与测试》学习笔记【第一章 软件测试基本概念】

目录 前言为什么要进行软件测试什么是软件缺陷1.1 什么是软件测试1.2 软件测试与CMMI软件质量保证SQA与软件测试的关系 1.3测试用例1.3.1什么是测试用例测试用例的五大要素测试用例1.3.2测试用例的评价标准1.3.3测试用例设计的基本原则1.3.4测试用例模板 1.4测试环境1.4.1什么是…

群晖NAS教程(十)、利用Docker安装蚂蚁笔记(leanote)

为了更好的浏览体验,欢迎光顾勤奋的凯尔森同学个人博客 群晖NAS教程(十)、利用Docker安装蚂蚁笔记(leanote) 蚂蚁笔记是一款特别棒的笔记软件,支持Markdown语法,是程序员必备的软件之一。下面我们就在群晖DS918+的机器上docker出来一个耍耍。 一、下载蚂蚁笔记(leanote)镜…

基于 Qt 框架的开源笔记软件 VNote

关注、星标公众号,直达精彩内容 来源:OSC开源社区 作者:tamlok VNote是一个受Vim启发开发的专门为Markdown而优化、设计的笔记软件。 授权协议:MIT 开发语言:C/C JavaScript HTML/CSS SHELL 操作系统:跨平台…

VisionPro软件笔记

VisionPro笔记 1、CogPMAlignTool的操作方法: 抓取图像-设置训练区域及参数-训练模板-设置运行参数与区域-运行-查看结果 2、CogPMAlignTool的基本原理: 图案位置搜索工具(识别定位)基于边缘特征的模板而不是基于像素的模板匹配…

一款开源的支持离线的支持MarkDown的优秀笔记软件----思源笔记

日常工作中,大家可能会用笔记软件记录自己积累的一些知识,组建自己的知识管理系统,常用的工具可能有云笔记,如有道云笔记,印象笔记等,但是有时候在工作中,信息比较敏感,不能够将信息…

一文了解常用效率记笔记软件(超过20款含有图片和双向链笔记)

前言 Mac 软件推荐下载网址 麦软网:https://www.macfz.com腾讯柠檬:https://lemon.qq.com/lab 更新时间 第七次更新 6 月 28 号 ,对于有道和印象的理解,有时间把这篇文章拆分下第六次更新 5 月 27 号,更新了如何看待…

知识管理软件,有道云笔记的优缺点和C笔记

前言 软件有道云笔记C笔记发布时间2011年6月28日还在内测所属公司网易公司北京创新乐知网络技术有限公司 1.笔记的重要性: 大家有没有一种种感受,我们成日钻研书籍,天天认真听讲,发奋学习,收到的反馈却并不理想&…

OneNote-做笔记的软件-强烈推荐

一、认识电子笔记本 普通笔记本转化为电子笔记本 笔记可以将我们的想法和从外部获取的信息进行归纳和整理,而电子笔记本就是将传统的笔记进行了电子化电子笔记本的优势 可搜索统一管理高效编辑可修改性多端同步主流电子笔记本 OneNoteEver note(印象笔记)Notability…

推荐几款好用的云笔记软件

一直钟爱印象笔记,程序员的电脑上必装的软件,但最近期限到了,再也不能像以前无限制的上传文件,续费也比去年的只要九块九一年高出了很多倍,因此,注册试用了其他的笔记,发现云笔记众多&#xff0…

php个人笔记系统 开源,Github精选!一款开源免费的轻量级笔记软件

更多精彩内容,请关注公众号【平凡而诗意】 ​ 笔记软件是工作和学习过程中经常会用到的软件,会议纪要、工作事项、待办,都需要用到笔记软件,这样能够明确做事的先后顺序,能够提高做事的效率。 笔记软件数不胜数&#x…

软件工程复习笔记 类图

类图 前言1 类图的概念1、类图2、类图的作用3、类图的组成元素 2 UML中的类(1)类的定义(2)类的表示(3)类的命名(4)类的属性&#xff0…

想找一款读书笔记软件?快来试试BookxNote

去年看到网上介绍 BookxNote 是一款做读书笔记的好工具,被誉为“ Windows 端的 MarginNote” 。当时试用了一下感觉挺好,但是在笔记和书籍的存储上还有一些困惑,因此有点顾虑。最近看教程和自己尝试,解决了困惑,在此分…