后一个任务等待前一个任务结束再执行。程序执行顺序与任务排列顺序一致的,同步的。

参考:

  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、改进为异步操作,不阻塞。异步编程的方法一:回调函数

function f1(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);
function f2(){
console.log("done");
}
function f1(){
setTimeout(function(){
doc.trigger("done")
}, 1000);
}
doc.on("done", f2);
f1();

发布订阅:和事件监听一模一样啊。

观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。

var Observable = {//doc
callbacks: [],
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);

而且,它还有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。这种方法的缺点就是编写和理解,都相对比较难。

javascript的回调函数 同步 异步的更多相关文章

  1. Javascript之回调函数(callback)

    1.回调函数定义: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方 ...

  2. 告诉你什么是javascript的回调函数

    函数也是对象 想弄明白回调函数,首先的清楚地明白函数的规则.在javascript中,函数是比较奇怪的,但它确确实实是对象.确切地说,函数是用Function()构造函数创建的Function对象.F ...

  3. javascript的回调函数

    函数也是对象 想弄明白回调函数,首先的清楚地明白函数的规则.在javascript中,函数是比较奇怪的,但它确确实实是对象.确切地说,函数是用Function()构造函数创建的Function对象.F ...

  4. 什么是javascript的回调函数?

    回调函数(callback) 基本上每本书里都会提一提实际上我们几乎每天都在用回调函数,那么如果问你到底什么是回调函数呢? 1. 回调函数是作为参数传递给另一个函数 2. 函数运行到某种程度时,执行回 ...

  5. JavaScript Callback 回调函数

    JavaScript callback回调函数 你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货.在这 ...

  6. node.js的作用、回调、同步异步代码、事件循环

    http://www.nodeclass.com/articles/39274 一.node.js的作用 I/O的意义,(I/O是输入/输出的简写,如:键盘敲入文本,输入,屏幕上看到文本显示输出.鼠标 ...

  7. JavaScript 之 回调函数的返回值给全局变量赋值问题

    jQuery 中,会遇到$.get(url,data,callback,type) 或 $.post(url,data,callback,type) 返回值给全局变量赋值的问题: 例如: <sc ...

  8. Node.js系列基础学习-----回调函数,异步

    Node.js基础学习 Node.js回调函数 Node.js异步编程的直接体现就是回调,异步编程依托回调来实现,但不是异步.回调函数在完成任务后就会被调用,Node有很多的回调函数,其所有的API都 ...

  9. JavaScript中回调函数的使用

    在JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A.我们就说函数A叫做回调函数.如果没有名称(函数表达式),就叫做匿名回调函数. ...

随机推荐

  1. poj 3071 Football(线段树+概率)

    Football Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2801   Accepted: 1428 Descript ...

  2. php中嵌套html代码和html代码中嵌套php方式

    php中嵌套html代码和html代码中嵌套php方式 一.总结 拷贝的话直接html代码是极好的方式 1.php中嵌套html代码(本质是原生php):a.原生嵌套<?php .....?&g ...

  3. vue项目实现导出数据到excel

    实现导出功能分两种,一种是客户端拿到数据做导出,第二种是服务器端处理好,返回一个数据流实现导出 第一种网上很容易找到,也很好用,本文要说的是第二种. fetchExport({ id: this.so ...

  4. u-boot-2011.06在基于s3c2440开发板的移植之引导内核与加载根文件系统

    http://www.linuxidc.com/Linux/2012-09/70510.htm  来源:Linux社区  作者:赵春江 uboot最主要的功能就是能够引导内核启动.本文就介绍如何实现该 ...

  5. ORACEL上传BLOB,深度遍历文件夹

    // uploadingDlg.cpp : 实现文件// #include "stdafx.h"#include "uploading.h"#include & ...

  6. Nginx+Tomcat搭建高性能负载均衡集群的实现方法

    一.    目标实现高性能负载均衡的Tomcat集群: 二.步骤 1.首先下载Nginx,要下载稳定版: 2.然后解压两个Tomcat,分别命名为apache-tomcat-6.0.33-1和apac ...

  7. 【52.49%】【codeforces 556A】Case of the Zeros and Ones

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  8. oracle分组取每组第一条数据

    oracle分组后取每组第一条数据   '数据格式     分组取第一条的效果   [sql] SELECT * FROM (SELECT ROW_NUMBER() OVER(PARTITION BY ...

  9. html5 背景音乐 js控制播放 暂停

    <html> <head> <title> 测试页面 </title> <script src="jquery.min.js" ...

  10. Seagate-保修验证(za25shrx)

    保修验证 http://support.seagate.com/customer/zh-CN/warranty_validation.jsp   Seagate   保修验证    End User  ...