理解javascript回调函数


Posted in Javascript onDecember 28, 2014

把函数作为参数传入到另一个函数中。这个函数就是所谓的回调函数

经常遇到这样一种情况,某个项目的A层和B层是由不同的人员协同完成.A层负责功能funA,B层负责funcB。当B层要用到某个模块的数据,于是他对A层人员说,我需要你们提供满足某种需求的数据,你给我提供一个接口。

A层的人员说:我给你提供数据,怎么展示和处理则是B的事情。
当然B层不可能为你每个需求都提供一个数据接口,B给A提供一个通过的接口.B得到数据,然后B写函数去展示。

即,你需要和其他人合作,别人提供数据,而你不需要关注别人获取或者构建数据的方式方法。你只要对这个拿到的数据进行操作。这时候就需要使用回调函数

因此,回调本质上是一种设计模式,并且jQuery(包括其他框架)的设计原则遵循了这个模式。

一个同步(阻塞)中使用回调的例子,目的是在func1代码执行完成后执行func2。

var func1=function(callback){

    //do something.

    (callback && typeof(callback) === "function") && callback();

}
func1(func2);

    var func2=function(){

}

异步回调的例子:

$(document).ready(callback);
    $.ajax({

        url: "test.html",

        context: document.body

    }).done(function() { 

        $(this).addClass("done");

    }).fail(function() { 

        alert("error");

    }).always(function() { 

        alert("complete"); 

    });

注意的是,ajax请求确实是异步的,不过这请求是由浏览器新开一个线程请求,当请求的状态变更时,如果先前已设置回调,这异步线程就产生状态变更事件放到 JavaScript引擎的处理队列中等待处理。见:http://www.phpv.net/html/1700.html

回调什么时候执行

回调函数,一般在同步情境下是最后执行的,而在异步情境下有可能不执行,因为事件没有被触发或者条件不满足。

回调函数的使用场合

资源加载:动态加载js文件后执行回调,加载iframe后执行回调,ajax操作回调,图片加载完成执行回调,AJAX等等。
DOM事件及Node.js事件基于回调机制(Node.js回调可能会出现多层回调嵌套的问题)。
setTimeout的延迟时间为0,这个hack经常被用到,settimeout调用的函数其实就是一个callback的体现

链式调用:链式调用的时候,在赋值器(setter)方法中(或者本身没有返回值的方法中)很容易实现链式调用,而取值器(getter)相对来说不好实现链式调用,因为你需要取值器返回你需要的数据而不是this指针,如果要实现链式方法,可以用回调函数来实现

setTimeout、setInterval的函数调用得到其返回值。由于两个函数都是异步的,即:他们的调用时序和程序的主流程是相对独立的,所以没有办法在主体里面等待它们的返回值,它们被打开的时候程序也不会停下来等待,否则也就失去了setTimeout及setInterval的意义了,所以用return已经没有意义,只能使用callback。callback的意义在于将timer执行的结果通知给代理函数进行及时处理。

网上收集一下资料,应该弄懂了,自己整理出一个例子:

function fun(num,callback){

    if(num<0)  { 

        alert("调用A层函数处理!");

        alert("数据不能为负,输入错误!"); 

    }else if(num==0){

        alert("调用A层函数处理!");

        alert("该数据项不存在!");

    }else{

        alert("调用B层函数处理!");

        callback(1);

    }

}

function test(){

    var num=document.getElementById("score").value;

    fun(num,function(back){ //匿名B层处理函数

alert(":"+back);

        if(num<2) 

            alert("数字为1");

        else if(num<=3) 

            alert("数字为2或3!");

        else 

            alert("数字大于3!"); 

    })

 }

当函数开始执行fun的时候,先跑去找判定num是否是负数或者为零,否则执行B层处理函数alert(":"+back);输出1,判定为<2、<=3、>3等情况。

经验小提示:

最好保证回调存在且必须是函数引用或者函数表达式:

(callback && typeof(callback) === "function") && callback();
 var obj={

        init : function(callback){

        //TODO ...

        if(callback && typeof(callback) === "function") && callback()){

              callback('init...');//回调

        }

    }

 
最后,关于为什么要使用回调函数呢?下面的比喻很生动有趣。

你有事去隔壁寝室找同学,发现人不在,你怎么办呢?

方法1,每隔几分钟再去趟隔壁寝室,看人在不
方法2,拜托与他同寝室的人,看到他回来时叫一下你

前者是轮询,后者是回调。

那你说,我直接在隔壁寝室等到同学回来可以吗?

可以啊,只不过这样原本你可以省下时间做其他事,现在必须浪费在等待上了。把原来的非阻塞的异步调用变成了阻塞的同步调用。

JavaScript的回调是在异步调用场景下使用的,使用回调性能好于轮询。

Javascript 相关文章推荐
javascript学习网址备忘
May 29 Javascript
JS array 数组详解
Mar 22 Javascript
iframe 上下滚动条如何默认在下方实现原理
Dec 10 Javascript
解析dom中的children对象数组元素firstChild,lastChild的使用
Jul 10 Javascript
jquery表单验证框架提供的身份证验证方法(示例代码)
Dec 27 Javascript
javascript中数组array及string的方法总结
Nov 28 Javascript
手机端 HTML5使用photoswipe.js仿微信朋友圈图片放大效果
Aug 25 Javascript
ES6实现的遍历目录函数示例
Apr 07 Javascript
vue+vuex+axio从后台获取数据存入vuex实现组件之间共享数据
Apr 22 Javascript
通过cordova将vue项目打包为webapp的方法
Feb 02 Javascript
Vue路由守卫之路由独享守卫
Sep 25 Javascript
JS实现audio音频剪裁剪切复制播放与上传(步骤详解)
Jul 28 Javascript
JavaScript设计模式之建造者模式介绍
Dec 28 #Javascript
如何编写高质量JS代码
Dec 28 #Javascript
JavaScript设计模式之原型模式(Object.create与prototype)介绍
Dec 28 #Javascript
javascript中定义类的方法汇总
Dec 28 #Javascript
js数组的操作指南
Dec 28 #Javascript
JavaScript设计模式之适配器模式介绍
Dec 28 #Javascript
javascript+canvas制作九宫格小程序
Dec 28 #Javascript
You might like
PHP概述.
2006/10/09 PHP
浅析PHP中Session可能会引起并发问题
2015/07/23 PHP
通过PHP自带的服务器来查看正则匹配结果的方法
2015/12/24 PHP
深入剖析PHP中printf()函数格式化使用
2016/05/23 PHP
PHP中quotemeta()函数的用法讲解
2019/04/04 PHP
jQuery的一些注意
2006/12/06 Javascript
基于Asp.net与Javascript控制的日期控件
2010/05/22 Javascript
js正文内容高亮效果的实现方法
2013/06/30 Javascript
JS实现网页上随机产生超链接地址的方法
2015/11/09 Javascript
浅谈JS使用[ ]来访问对象属性
2016/09/21 Javascript
AngularJS 文件上传控件 ng-file-upload详解
2017/01/13 Javascript
vue.js 左侧二级菜单显示与隐藏切换的实例代码
2017/05/23 Javascript
php简单数据库操作类的封装
2017/06/08 Javascript
vue中的模态对话框组件实现过程
2018/05/01 Javascript
解决VUE双向绑定失效的问题
2019/10/29 Javascript
bootstrap-table后端分页功能完整实例
2020/06/01 Javascript
利用vue3+ts实现管理后台(增删改查)
2020/10/30 Javascript
[04:15]DOTA2-DPC中国联赛1月19日Recap集锦
2021/03/11 DOTA
Python基于Tkinter实现的记事本实例
2015/06/17 Python
python3 shelve模块的详解
2017/07/08 Python
安装Pycharm2019以及配置anconda教程的方法步骤
2019/11/11 Python
如何通过Django使用本地css/js文件
2020/01/20 Python
详解Python中pyautogui库的最全使用方法
2020/04/01 Python
在pycharm中使用matplotlib.pyplot 绘图时报错的解决
2020/06/01 Python
python实现图书馆抢座(自动预约)功能的示例代码
2020/09/29 Python
css3截图_动力节点Java学院整理
2017/07/11 HTML / CSS
CSS3网格的三个新特性详解
2014/04/04 HTML / CSS
HTML5 Canvas渐进填充与透明实现图像的Mask效果
2013/07/11 HTML / CSS
Otticanet英国:最顶尖的世界名牌眼镜, 能得到打折季的价格
2019/02/10 全球购物
班主任经验交流会主持词
2014/04/01 职场文书
八一建军节慰问信
2015/02/14 职场文书
安全学习心得体会范文
2016/01/18 职场文书
幼儿园教师教学反思
2016/03/02 职场文书
2019年关于小学生课外阅读情况的分析报告
2019/12/02 职场文书
Python Pandas pandas.read_sql函数实例用法
2021/06/21 Python
Vue中使用import进行路由懒加载的原理分析
2022/04/01 Vue.js