@GivenCui
2016-12-28T09:07:28.000000Z
字数 3166
阅读 745
node
回调就是把函数a作为参数 (函数引用) 传递到另一个函数b中
A callback is a function that is passed as an argument to another function and is executed after its parent function has completed. The special thing about a callback is that functions that appear after the "parent" can execute before the callback executes.
特点: 回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
举例:
1. 你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件
2. 有一家旅馆提供叫醒服务,但是要求旅客自己决定叫醒的方法。可以是打客房电话,也可以是派服务员去敲门,睡得死怕耽误事的,还可以要求往自己头上浇盆水。这里,“叫醒”这个行为是旅馆提供的,相当于库函数,但是叫醒的方式是由旅客决定并告诉旅馆的,也就是回调函数。而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作,称为登记回调函数(to register a callback function)
编程分为两类:系统编程(system programming)和应用编程(application programming)。所谓系统编程,简单来说,就是编写库;而应用编程就是利用写好的各种库来编写具某种功用的程序,也就是应用。系统程序员会给自己写的库留下一些接口,即API(application programming interface,应用编程接口),以供应用程序员使用。所以在抽象层的图示里,库位于应用的底下。
当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数(callback function)。
同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)
1. 同步: 在发出一个"调用"时,"调用者"主动等待"调用"结果
2. 异步: 发送一个请求,不等待返回,随时可以再发送下一个请求
// 在js中用
// 回调
// 同步与异步
// 异步举例: setTimeout(), setInterval()
// 同步
(function () {
console.log("** 同步");
var c = 0;
function show() {
console.log(" 结果为"+c);
}
function plus() {
c++;
}
plus();
show();
})();
// 异步影响结果
(function () {
console.log("** 异步")
var c = 0;
function show() {
console.log(" 结果为"+c);
}
function plus() {
setTimeout(function () {
c++;
},0);
}
plus();
show();
})();
// 异步 + 回调
(function () {
console.log("** 异步 + 回调")
var c = 0;
function show() {
console.log(" 结果为" + c);
}
function plus(cb) {
setTimeout(function () {
c++;
cb(c);
},0);
}
plus(show);
})();
// 补充setTimeout() 的机理
// setTimeout并不是真正的异步操作,只是把想执行的代码放到UI队列中,在未来某个点执行
// 第一种情况
// setTimeout里的都在一个任务队列
setTimeout(function() {
while (true) {
}
}, 100);
setTimeout(function() {
alert('你好!');
}, 200);
// 第二种情况
// 输出a
<input type="text" value="a" name="input" onkeydown="alert(this.value)" />
// 输出a和按下的字母
<input type="text" value="a" name="input" onkeydown="var me=this;setTimeout(function(){alert(me.value)},0)" />
// 第三种情况
// 一直死循环, setTimeout一直在等待,没有机会执行
var t = true;
setTimeout(function(){ t = false; }, 1000);
while(t){ }
alert('end');
编程语言的I/O类库中常常使用流这个抽象的概念,它代表任何有能力产生数据的数据源对象或时有能力接收数据的接收端对象。“流”概念源于UNIX中的管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等,它屏蔽了实际的I/O设备中处理数据的细节。 一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。
1 :流:一组有序的数据序列。
2:字节流:数据流中最小的数据单元是字节。
3:字符流:数据流中最小的数据单元是字符。
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
非阻塞、单线程、事件驱动
老张爱喝茶,废话不说,煮开水。
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
1 老张把水壶放到火上,立等水开。(同步阻塞)
老张觉得自己有点傻
2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。
3 老张把响水壶放到火上,立等水开。(异步阻塞)
老张觉得这样傻等意义不大
4 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
老张觉得自己聪明了。
所谓同步异步,只是对于水壶而言。
普通水壶,同步;响水壶,异步。
虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。
同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。
所谓阻塞非阻塞,仅仅对于老张而言。
立等的老张,阻塞;看电视的老张,非阻塞。
情况1和情况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。