关于js的callback回调函数的理解

回调函数的处理逻辑理解:

所谓的回调函数处理逻辑,其实就是先将回调函数的代码 冻结(或者理解为闲置),接着将这个回调函数的代码放到回调函数管理器的队列里面。

待回调函数被触发调用的时候,对应的回调函数的代码才会从管理器队列取出来并自动执行(激活回调函数的代码),实现异步的编程效果。

不过,对于一些必须要等回调函数执行完毕才可以确定的动作,实际上,就是会掉入一个层层回调的局面了。这点也是回调函数的复杂的地方!

换句话说,只要您要获取的值是要被回调才确定的,那接下来的所有代码都必须用回调的方式来编写,层层嵌套。

以百度提问的一个例子简单说明:

问题:

js 回调函数问题的执行结果想作为返回值

function receive()

{

var re_data;

client.on(‘data‘, function(data) {

re_data = data;

console.log(data);

client.end();

});

return re_data ;

}

receive这个函数的目的是返回接受到的数据(data),但data值在一个回调函数里面,总是先执行return ,再执行回调函数,因此返回值总是undefined,有什么办法可以解决吗?

解决办法:

建议改变你的思维方式,将你的函数 receive 也改成回调式的:

function receive(callback){

// ....

client.on(‘data‘, function(data) {

callback(data);

});

}

然后,别的地方要调用receive函数,则将这个函数获取的值之后的所有动作都封装在回调函数callback里面。

例如:

aaaa;

receive(function(data){

//这里下面的代码都可以获取data了。

data....的处理。。。

});

关于回调函数的另外一个更加形象的说法:

上下文:假设A函数调用B函数(B函数是异步式的),调用函数A是父函数,被调用的函数B是子函数。

回调函数例子:父亲让儿子去做一个事情,完成之后会给一个红包(给儿子)。然后父亲立刻去拉屎了。

分析例子:

首先,事情必须要完成之后才可以给红包。另外,红包的钱当然是父亲给,儿子只需要在完成之后,自己拆开红包即可。当然,儿子并不用知道父亲会给多少钱。

很简单吧?其实回调函数也就是这样子的思路。

父亲让儿子去做一个事情-->父亲函数调用儿子的函数方法。这个儿子的函数方法是异步的,并不会影响父亲的下一步动作(拉屎)。

红包-->回调函数的名称。也就是callback名称。儿子只需要确定拆开它(执行它)即可。至于里面是什么,有多少钱,儿子管不了,由父亲决定。

红包里面的钱-->可以理解为回调函数所执行的代码段。这个当然是由父亲提供!

儿子完成之后才可以拆红包-->儿子函数完成之后,才会调用父亲提供的一个回调函数(也就是拆红包,数钱)。

另外一个角度的形象理解:

回调函数给人感觉更加符合实际。反正要什么,就调用对应的函数获取信息。

等信息获取之后,还想做什么事情(例如完成之后要主动通知我),就可以将逻辑自己写入到回调函数里面,让被调用的函数自动执行该回调函数的代码,完成整个过程!

备注:一定需要注意的是,函数如果是异步的,则整个代码都是异步执行。并不会影响主调用的函数的代码的执行顺序。这就是所谓的异步!

现在问题来了,特别是一些嵌套的回调函数,如何理解呢?

现在让我们理解一下所谓的嵌套的异步回调函数。

简单理解方法:

主函数的代码实际上还是按照顺序执行的。

只要是封装在回调函数里面的代码,都是要等待最深层的回调函数执行之后,才会逐一执行前一层的回调函数的代码!

另外一个理解:我不需要知道你是怎么做的,你只需要做好之后告诉我,并且告诉我结果,即可。我只要结果!

如果是要等到知道结果才可以继续做的事情,则就是要写在等待别人告诉我之后才可以做的事情列表里面(回调函数的事情);

如果是别的事情,例如拉屎拉尿什么的,立刻就去做,无需等待!

举个例子:

我向要二级供应商要2块镀膜的建筑玻璃。我不需要知道这个玻璃怎么制作的,玻璃怎么到一级供应商的,怎么到二级供应商的。

反正你二级供应商能提供给我要求的玻璃就可以了,提供之后要告诉我是多少价格的,好让我准备付款给你。

-->需要注意的是,我收到了建筑玻璃,我才可以做安装玻璃等等的动作。

但是,拉屎拉尿什么的,我想什么时候做就什么时候做,和购买玻璃并没什么关系。

其实上面的例子就是一个嵌套的回调函数。

制造过程函数:

var make = function(qty,type,callback){

//接到订单,也要检查数量和类型。有些类型可能无法生产!

makeCheck();

//根据qty数量和type类型来制造需要的玻璃

//要经过很多道工序的生产。。。

factory.makeGlass();

//做完之后,就调用回调函数,通知已经制造好啦!可以来拿货。当然要收钱啊。就是提供价格给调用者(批量出厂的价格)。

var amount=100元

callback(amount);

}

一级供应商函数:

var vendor1 = function(qty,type,callback){

//接到订单,也要重复做检查数量和类型。

vendor1Check();

//向工厂订货。要的数量和类型是需要指定的。一级供应商不需要知道怎么制造的,只需要通知工厂要货即可

make(qty,type,function(amount){

//工厂制造完毕,接到工厂的报价之后,这里一级供应商当然要赚钱,所以要加价10%

var vendorAmount=amount*1.1;

//执行父亲提供的回调函数代码,并且通知一级供应商提供的价格是多少(主动提供回调函数的参数)。

callback(vendorAmount);

});

}

二级供应商函数:

var vendor2 = function(qty,type,callback){

//接到订单,接着检查数量和类型是否正确。是否可以生产这种类型的玻璃。

vendor2Check();

//二级供应商不需要知道货是哪里拿的,只需要通知一级供应商要货即可

//接着向一级供应商订货。要的数量和类型是需要指定的

vendor1(qty,type,function(amount){

//货到,接到一级供应商的报价之后,这里二级供应商当然要赚钱,所以要加价20%

var vendorAmount=amount*1.2;

//执行对外的回调函数,并且通知用户,它提供的价格是多少。

callback(vendorAmount);

});

}

用户函数:

用户是最终的消费者。

var user = {

//用户购买玻璃的函数方法:

userBuy: function(qty,type,callback){

//核对数量是否正确,玻璃类型是否是需要的。

userCheck();

//用户向二级供应商拿货。需要注意的是,到货之后就可以进行安装等动作。都写在callback里面。

vendor2(qty,type,function(amount){//调用二级供应商的接口。并且写好回调函数,知道价格之后做什么。

//这里写的是玻璃到货之后的执行的动作。可能是10天之后才执行的。

user.receive();//用户收货

user.check();//用户检查货物质量

user.pay(amount);//用户付款

callback;//这里执行一个回调函数,可以是安装玻璃,甚至可以送给别人等等。由调用者决定做什么事情。

});

},

吃饭:function(){xxxxx},

拉屎:function(){xxxxx},

sleep:function(){xxxxx},

}

基于上面所定义的函数方法,模拟一个现实的例子:

用户早上吃饭,中午买玻璃,下买玻璃的订单之后,接着拉个屎,再睡觉。

试想一下,如果要等到玻璃来到之后才可以拉屎,那岂不是被憋死了。

----程序处理过程:

user.吃饭();

//买玻璃

user.userBuy(10,‘镀膜建筑玻璃‘,function(amount){

user.安装玻璃();

});

user.拉屎();//由于买玻璃是异步函数,所以,这里发出买玻璃的请求(调用买玻璃的函数)之后,立刻可以去拉屎了,片刻不影响!

user.sleep();//用户拉屎完毕,舒服了,睡觉去!

上面的例子可以看到,实际上回调函数是层层执行的。执行完最深的那层,再逐一向上执行。

执行用户购买玻璃的方法的时候,程序的执行顺序:

主函数的执行顺序:

userBuy(用户调用购买货物的方法)         父

-->vendor2(二级供应商提供货物的方法)    子

-->vendor1(一级供应商提供货物的方法)    孙

-->make(工厂制造过程的方法)             曾孙

而每个主函数所编写的的回调函数的代码的执行顺序:

make.cb(工厂制造完毕,会调用回调函数[执行(父级的)一级供应商提供的代码],相当于通知一级供应商,货物已经完成!价格是多少。)

-->vendor1.cb(一级供应商确认工厂制造完成,调用回调函数[执行二级供应商提供的代码],通知二级供应商,货物已经有了,价格是多少。这时候的价格已经加价10%)

需要注意的是,必须要等到生产完成并知道工厂提供的实际价格是多少,才可以加价。所以加价的代码由vendor1主动提供,但是执行由工厂用callback执行!

-->vendor2.cb(二级供应商拿到货,调用回调函数[执行用户购买所提供的代码],通知用户,货物已经有了,价格是多少。这时候价格又加了20%。真黑!)

-->userBuy.cb(用户拿到货了,先验货并付款,并调用回调函数[执行玻璃到货之后的代码,也就是调用user.userBuy的时候编写的回调代码,例如安装玻璃什么的]。流程走完!)

可以看出,嵌套的回调函数的执行顺序是逆向逐步执行。

每一个回调函数代码只和其儿子有关系。儿子做完之后,自动执行回调函数[父亲所写好的代码]。

也可以这样子说:

父亲调用儿子的方法,并向儿子写好回调函数执行的代码。儿子的回调函数的代码由父亲提供。名称是就是callback。

总结:

所谓的回调函数,就是由调用函数提供执行代码,被调用函数执行完毕之后,再自动执行的一个函数。异步式。

如果是嵌套的回调函数,就是,调用函数的回调函数嵌入到被调用函数所运行的回调函数代码之间(执行)的函数。就是callback代码中的callback函数。嵌套回调!

时间: 2024-11-07 05:13:19

关于js的callback回调函数的理解的相关文章

js中的回调函数的理解和使用方法

一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为函数实际上是一种对象,它可以存储在变量中,通过参数传递给另一个函数,在函数内部创建,从函数中返回结果值",因为函数是内置对象,我们可以将它作为参数传递给另一个函数,到函数中执行,甚至执行后将它返回,它一直被"专业的程序员"看作是一种难懂的技术. 回调函数的英文解释为: A callback is a functi

callback回调函数的理解

callback采用的设计模式是:模板模式,他的设计理念是基于面向对象中的多态的. 我们的程序中走到某个地方他会出现不一样的动作的时候,我们在这儿就使用回调函数.我们利用的就是 多态的原理,我们传递不同的类过来的时候就会出现不一样的动作. public class PaintFrame {    public static void drawPaint(MyFrame m){        System.out.println("1111111");        System.out

Android中回调函数的理解---本人Android纯新手

本人大二,刚刚接触Android,也刚刚申请的cnblog博客,说一下对Android中回调函数的理解,Android中回调函数和C++.JAVA中的默认构造函数差不多,即运行到了一定的代码时自动调用的代码,而Android中的回调函数和C++.JAVA中的默认构造函数的区别在于:C++.JAVA中的默认构造函数在创建一个对象时自动调用,而Android中的回调函数的自动调用是在比如按了HOME键之后.

【juincen】Java中的接口interface类比js中的回调函数

前几天在左讯飞语音的时候,无意间意识到java中的接口和js中常用的回调函数有点类似,今天在这儿整理一下思路. interface,Java中的接口,为什么会有这个东西. 一,预留声明 比如两个程序员A和B,A要写一段程序,其中需要调用到B写的程序.这时候A可以写一个接口: public interface Demo{ void deal(); } A要调用的方法先“预留声明”在接口里:deal 然后B去完善这个接口,B写了一个实现类实现了这个Demo接口. A在自己的业务逻辑里面只用调用接口的

JS回调函数(理解篇)

概述: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应. 定义: 在JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A.我们就说函数A叫做回调函数.如果没有名称(函数表达式),就叫做匿名回调函数. 因此callba

关于js中的回调函数callback,通俗易懂

前言 其实我一直很困惑关于js 中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制一下前人代码,功能实现了也就不再去追其原由,这么着,这个callback的概念就越来越混乱,因为你总感觉它是你Ajax请求后调用的那个函数,又感觉它是你某一个函数中的形参而已,而当你有一天看到一点关于Node.js的代码后你会更加崩溃,因为你会发现很多的callback,但是这么着下去肯定是不行的,因为很多的东西如果只是知道概念和理论,没有实践出结果,没有思考和感受,这些东西永远不

JS 对于回调函数的理解,和常见的使用场景应用,使用注意点

  很经常我们会遇到这样一种情况: 例如,你需要和其他人合作,别人提供数据,而你不需要关注别人获取或者构建数据的方式方法. 你只要对这个拿到的数据进行操作. 这样,就相当于我们提供一个外在的函数,别人调用这个函数,返回相应的数据. 例如: ? 1 2 3 4 5 6 7 8 function (num , numFun) { if(num < 10){ //do sth }else { //do sth numFun(); } } 在num的判断之后执行NumFun的函数. 所谓的回调函数,可以

callback回调函数理解 相当于this指针

1.callback函数在微软的官方手册中是这样定义callback函数的:"callback函数是由应用程序定义而由操作系统调用的函数".   凡是由用户设计而却由windows系统调用的函数,统称为callback函数,这些函数都有一定的类型,以配合windows的调用操作.      某些api函数以callback作为其参数之一,这些api,如settimer.linedda.enumobjects.通常这种api会在进行某 种行为之后或满足某种状态之时调用该callback函

js中的回调函数

回调就是一个函数的调用过程.那么就从理解这个调用过程开始吧.函数a有一个参数,这个参数是个函数b,当函数a执行完以后执行函数b.那么这个过程就叫回调. 其实中文也很好理解:回调,回调,就是回头调用的意思.函数a的事先干完,回头再调用函数b. 这里必须清楚一点:函数b是你以参数形式传给函数a的,那么函数b就叫回调函数. 也许有人有疑问了:一定要以参数形式传过去吗,我不可以直接在函数a里面调用函数b吗?确实可以.求解中. <解惑:如果你直接在函数a里调用的话,那么这个回调函数就被限制死了.但是使用函