javascript的回调函数 同步 异步
后一个任务等待前一个任务结束再执行。程序执行顺序与任务排列顺序一致的,同步的。
参考:
http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html
https://segmentfault.com/q/1010000000140970
在JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A。我们就说函数A叫做回调函数。如果没有名称(函数表达式),就叫做匿名回调函数。
因此callback 不一定用于异步,一般同步(阻塞)的场景下也经常用到回调,比如要求执行某些操作后执行回调函数。
1、一个同步(阻塞)中使用回调的例子
var func1=function(callback){//do something.(callback && typeof(callback) === "function") &&callback(); }var func2=function(){} func1(func2);
2、改进为异步操作,不阻塞。异步编程的方法一:回调函数
functionf1(callback){setTimeout(function() {//f1的任务代码 callback();},1000);} f1(f2)
采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。
回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。
3、回调总结
异步回调的例子:
$(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执行的
- 结果通知给代理函数进行及时处理。
回调函数的传递
上面说了,要将函数引用或者函数表达式作为参数传递。
$.get('myhtmlpage.html', myCallBack);//这是对的 $.get('myhtmlpage.html', myCallBack('foo', 'bar'));//这是错的,那么要带参数呢? $.get('myhtmlpage.html', function(){//带参数的使用函数表达式 myCallBack('foo', 'bar'); });
另外,最好保证回调存在且必须是函数引用或者函数表达式:
(callback && typeof(callback) === "function") && callback();
4、异步编程的方法二:事件监听(和发布订阅模式原理一样)
事件监听:
var doc =$(document);functionf2(){console.log("done");}functionf1(){setTimeout(function(){doc.trigger("done")},1000);}doc.on("done", f2);f1();
发布订阅:和事件监听一模一样啊。
观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。
var Observable ={//doccallbacks: [],add:function(fn) {this.callbacks.push(fn);},fire:function() {this.callbacks.forEach(function(fn) {fn();})} } Observable.add(function() {alert(1) })Observable.add(function() {alert(2) }) Observable.fire();//1, 2
4、异步编程的方法三:promise对象
Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。
简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:
f1().then(f2);
f1要进行如下改写(这里使用的是jQuery的实现):
function f1(){
var dfd = $.Deferred();
setTimeout(function () {
// f1的任务代码
dfd.resolve();
}, 500);
return dfd.promise;
}
这样写的优点在于,回调函数变成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现许多强大的功能。
比如,指定多个回调函数:
f1().then(f2).then(f3);
再比如,指定发生错误时的回调函数:
f1().then(f2).fail(f3);
而且,它还有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。这种方法的缺点就是编写和理解,都相对比较难。
转载于:https://www.cnblogs.com/darr/p/5207593.html
javascript的回调函数 同步 异步相关推荐
- javascript利用回调函数解决异步困扰
虽然已经存在promise,StratifiedJS等工具用来解决回调地狱,但是讲真,我觉得他们也并没有让代码的可读性大大增强,而且在回调函数的嵌套次数有限的情况下也不至于成为一个"地狱&q ...
- 有关JavaScript中回调函数的所有内容!
作者:Shadeed 译者:前端小智 来源:dmitripavlutin 点赞再看,微信搜索**[大迁世界],B站关注[前端小智]**这个没有大厂背景,但有着一股向上积极心态人.本文 GitHub h ...
- JavaScript:回调函数(callback)
前言 callback,大家都知道是回调函数的意思.如果让你举些callback的例子,我相信你可以举出一堆.但callback的概念你知道吗?你自己在实际应用中能不能合理利用回调实现功能? 我们在平 ...
- 如何用JavaScript的回调函数做出承诺
by Adham El Banhawy 由Adham El Banhawy 如何用JavaScript的回调函数做出承诺 (How to make a Promise out of a Callbac ...
- 彻底理解JavaScript中回调函数 (推荐)
在javascript中回调函数非常重要,它们几乎无处不在.像其他更加传统的编程语言都有回调函数概念,但是非常奇怪的是,完完整整谈论回调函数的在线教程比较少,倒是有一堆关于call()和apply() ...
- ajax回调函数有时成功有时失败,javascript - Ajax 回调函数行为随机。我做错了什么?...
我有以下行为随机的 ajax 函数.有时会显示警报 success finally.在其他情况下,第二个警报是 显示 Failure: my status is 500. promptId 从调用函数 ...
- js回调函数获取异步返回值
js回调函数获取异步返回值 1.尝试获取异步返回值 function test(){var res = 0;setTimeout(function(){res = 1;},1000)return re ...
- 回调函数 同步回调 异步回调
回调函数 回调函数一般是在封装接口的时候,回调显得特别重要,我们首先假设有两个程序员在写代码,A程序员写底层驱动接口,B程序员写上层应用程序,然而此时底层驱动接口A有一个数据d需要传输给B,此时有两种 ...
- javascript之回调函数小知识
Javascript异步编程方法------"回调函数" 这是异步编程最基本的方法. 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用.回调和异步调用. ...
最新文章
- 复习计算机网络day2
- LeetCode1117. Building H2O --Java解法--多线程保证执行顺序--AtomicInteger
- 如何取消linux响铃_linux初学者入门:VIM编辑简易指南(常用操作)
- One Switch for Mac 一键切换系统各项功能
- 虚幻填坑004:减少starter content占用空间,只保留使用的assets
- CTFshow 反序列化 web272
- matplotlib xticks yticks
- Nginx配置https和wss
- 《那些年啊,那些事——一个程序员的奋斗史》——54
- 艰苦的编译boost python (失败)
- Android TextView文字超出一屏不能显示其它的文字 解决方案
- Android widget开发有感
- 你的目的是什么是谁指使你_魔家四将的师傅是谁?隐藏的高人,只配合太上老君的布局...
- 线程并行化的概念及其用法
- 基于公网smtp协议实现邮件服务器
- 资深技术专家张荣华:架构的方法论
- AAAI 2020上的NLP有哪些研究风向?
- 白盒测试哪种测试效果好_比较常用的白盒测试工具有哪些?
- 深度学习--- GAN网络原理解析
- 商务统计_5 用图表演示数据 - 茎叶图
热门文章
- 一文带你读懂单目视觉SLAM数据关联优化
- 《Python编程从入门到实践》记录之Python函数传递任意数量的实参
- 想学数学建模???先来看会这几个MATLAB题吧!!!(一)
- python处理mat数据_python读取.mat文件的数据及实例代码
- Linux gedit
- linux 命令如何输入,Linux 命令行输入
- Redis入门(三)Redis的基本数据类型
- 使用uiautomator2进行webview页面的测试
- An invalid form control with name='timeone[]' is not focusable.
- sql 查询所有数据库-表-表结构