回调 订阅
回调(huí tiáo 外文名 Retracement),是指在价格上涨趋势中,价格由于上涨速度太快,受到卖方打压而暂时回落的现象。回调幅度小于上涨幅度,回调后将恢复上涨趋势。回调(huí diào 外文名 Callback),是指回调函数,编程术语。 展开全文
回调(huí tiáo 外文名 Retracement),是指在价格上涨趋势中,价格由于上涨速度太快,受到卖方打压而暂时回落的现象。回调幅度小于上涨幅度,回调后将恢复上涨趋势。回调(huí diào 外文名 Callback),是指回调函数,编程术语。
信息
定    义
指在价格上涨趋势中
分    为
回调时间、回调力度、回调量能
中文名
回调
外文名
Retracement
回调编程回调
软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础,因此,下面我们着重讨论回调机制在不同软件架构中的实现。对于不同类型的语言(如结构化语言和对象语言)、平台(Win32、JDK)或构架(CORBA、DCOM、WebService),客户和服务的交互除了同步方式以外,都需要具备一定的异步通知机制,让服务方(或接口提供方)在某些情况下能够主动通知客户,而回调是实现异步的一个最简捷的途径。对于一般的结构化语言,可以通过回调函数来实现回调。回调函数也是一个函数或过程,不过它是一个由调用方自己实现,供被调用方使用的特殊函数。在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类称为回调类,回调类的对象称为回调对象。对于像C++或Object Pascal这些兼容了过程特性的对象语言,不仅提供了回调对象、回调方法等特性,也能兼容过程语言的回调函数机制。Windows平台的消息机制也可以看作是回调的一种应用,我们通过系统提供的接口注册消息处理函数(即回调函数),从而实现接收、处理消息的目的。由于Windows平台的API是用C语言来构建的,我们可以认为它也是回调函数的一个特例。对于分布式组件代理体系CORBA,异步处理有多种方式,如回调、事件服务、通知服务等。事件服务和通知服务是CORBA用来处理异步消息的标准服务,他们主要负责消息的处理、派发、维护等工作。对一些简单的异步处理过程,我们可以通过回调机制来实现。
收起全文
精华内容
下载资源
问答
  • 回调函数

    千次阅读 多人点赞 2019-09-09 17:36:28
    回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定...

    回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

    其实回调就是一种利用函数指针进行函数调用的过程.

    为什么要用回调呢?比如我要写一个子模块给你用,来接收远程socket发来的命令.当我接收到命令后,需要调用你的主模块的函数, 来进行相应的处理.但是我不知道你要用哪个函数来处理这个命令,我也不知道你的主模块是什么.cpp或者.h,或者说,我根本不用关心你在主模块里怎么处理它,也不应该关心用什么函数处理它......怎么办呢?使用回调!

    —— lone wolf

    使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。

    —— 某专家

    回调函数,就是由你自己写的。你需要调用另外一个函数,而这个函数的其中一个参数,就是你的这个回调函数名。这样,系统在必要的时候,就会调用你写的回调函数,这样你就可以在回调函数里完成你要做的事。

    —— 绿叶

    回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统信息或处理异步事件。应用程序把回调函数的地址指针告诉DLL,而DLL在适当的时候会调用该函数。回调函数必须遵守事先规定好的参数格式和传递方式,否则DLL一调用它就会引起程序或系统的崩溃。通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall,当然,DLL编制者可以自己定义调用方式,但客户程序也必须遵守相同的规定。在__stdcall方式下,函数的参数按从右到左的顺序压入堆栈,除了明确指明是指针或引用外,参数都按值传递,函数返回之前自己负责把参数从堆栈中弹出。

    —— jufengfeng

    看了这么多的资料,我只将每位的定义总结一下就一句话:使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己写的一个函数(这个函数就是回调函数)的地址作为参数传递给那个函数。回调其实就是提供使用某模块的一种方法。回调函数就好比是一个中断处理函数。

     

    3. 回调函数的作用?应该在什么情况下使用?

    用过STL的人都知道,在STL中众多算法和程序都用到回调函数,这实现了一种策略。只要任何符合我的标准的函数和计算都可以用我这个公式。你可以实现各种各样的回调函数,只要符合我的格式就能用。就上面的程序来说,你只要函数格式符合cllback第二个参数的格式不论你给别人做饭、铺床叠被都可以正常工作。这就是回调的作用,把回调实现留给别人。这是一个用法。
    有一位朋友用分层的概念来解释了回调机制:callback函数为B层,main函数和print函数为A层,A层调用了B层的回调函数callmeback,而B层的回调函数调用了A层的实现函数print。说白了B层就是一个接口。

    有一位朋友用分层的概念来解释了回调机制:callback函数为B层,main函数和print函数为A层,A层调用了B层的回调函数callmeback,而B层的回调函数调用了A层的实现函数print。说白了B层就是一个接口。
    最后要注意的是:回调函数要么是全局函数,要么是静态函数!

    
    #include <stdio.h>
    //回调函数
    int ADD(int (*callback)(int,int), int a, int b){
    	return (*callback)(a,b);//此处回调add函数...
    }
    //普通函数
    int add(int a, int b){
    	return a + b;
    }
     
    int main(void){
    	printf("%d\n",add(1,2));
    	printf("%d\n",ADD(add,1,2));
    	return 0;
    }

     

    C回调函数

    C++回调函数扩展自C回调函数,要想理解C++回调函数,先要理解C回调函数。我们通过一个实例来讲解C回调函数的使用方法。

    //callbackTest.c
    //1.定义函数onHeight(回调函数)
    //@onHeight 函数名
    //@height   参数
    //@contex   上下文
    void onHeight(double height, void* contex)
    {
    	sprint("current height is %lf",height);
    }
    
    //2.定义onHeight函数的原型
    //@CallbackFun 指向函数的指针类型
    //@height      回调参数,当有多个参数时,可以定义一个结构体
    //@contex      回调上下文,在C中一般传入nullptr,在C++中可传入对象指针
    typedef void (*CallbackFun)(double height, void* contex);
    
    //3.定义注册回调函数
    //@registHeightCallback 注册函数名
    //@callback             回调函数原型
    //@contex               回调上下文
    void registHeightCallback(CallbackFun callback, void* contex)
    {
    	double h=100;
    	callback(h,nullptr);
    }
    
    //4.main函数
    void main()
    {
    	//注册onHeight函数,即通过registHeightCallback的参数将onHeight函数指针
    	//传入给registHeightCallback函数,在registHeightCallback函数中调用
    	//callback就相当于调用onHeight函数。
    	registHeightCallback(onHeight,nullptr);
    }

    程序的运行结果是:
    current height is 100
    很多时候,注册的时候并不调用回调函数,而是在其他函数中调用,那我们可以定义一个CallbackFun全局指针变量,在注册的时候将函数指针赋给它,在要调用的调用它。如

    //定义全局指针变量
    CallbackFun* m_pCallback;
    //定义注册回调函数
    void registHeightCallback(CallbackFun callback, void* contex)
    {
    	m_pCallback = callback;
    }
    //定义调用函数
    void printHeightFun(double height)
    {
    	m_pCallback(height,nullptr);
    }
    //main函数
    void main()
    {
    	//注册回调函数onHeight
    	registHeightCallback(onHeight,nullptr);
    	//打印height
    	double h=99;
    	printHeightFun(99);
    }

     程序的运行结果是:
    current height is 99

    C++回调函数

    C++回调函数扩展自C,与C略有不同的是,C++可以使用全局函数和静态函数作为回调函数。考虑到全局函数会破坏封装性,所以一般都用静态成员函数。故除了理解函数指针,还要理解静态成员函数,具体一点是在静态成员函数中访问非静态成员函数的方法,因为我们很可能需要获取静态成员函数中的数据。

    使用场景描述

    比如说你使用了别人提供的sdk,这个sdk可能来自供应商,也有可能来自你的同事,他就提供给你一个注册回调函接口,比如就下面这个,你可以通过回调函数获取到height(某种传感器的实时返回的数据),你要怎么做?

    C++回调函数定义

    //CallbackFun类型
    //@CallbackFun 指向函数的指针类型
    //@height      回调参数,当有多个参数时,可以定义一个结构体
    //@contex      回调上下文,在C中一般传入nullptr,在C++中可传入对象指针
    typedef void (*CallbackFun)(double height, void* contex);
    
    //注册回调函数接口
    //@registHeightCallback 注册函数名
    //@callback             回调函数原型
    //@contex               回调上下文
    void registHeightCallback(CallbackFun callback, void* contex)

    首先,你要定义一个静态成员函数并注册。

    //sensorTest.cpp
    //接收数据类class Sensor
    class Sensor{
    public:
    	Sensor(){}
    	~Sensor(){}
    	//定义回调函数onHeight
    	static void onHeight(double height, void* contex)
    	{
    		cout << "current height is  " << height << endl;
    	}
    	//定义注册回调函数
    	void registCallback()
    	{
    		registHeightCallback(onHeight, this);
    	}
    }
    
    //main 函数
    void main()
    {
    	Sensor sens;
    	sens.registCallback();
    }

    运行程序,我们发现控制台一直在打印
    current height is **
    说明我们的回调函数正确实现了。到这一步不难,只要掌握基本的回调函数概念都能实现。
    现在我们有这样一种情况,我们有另外一个类,要在这个类里面实时打印获取的数据,要怎么做呢?

    静态成员函数访问非静态成员函数的方法

    我们知道静态成员函数中是只能出现静态变量和静态函数的,但是有些时候真的需要访问非静态成员函数或变量,比如我上面说的那种情况。让我们先来实现对同一个类中的非静态成员函数的访问。
    修改class Sensor如下

    //接收数据类class Sensor
    class Sensor{
    public:
    	Sensor(){}
    	~Sensor(){}
    	//定义回调函数onHeight
    	static void onHeight(double height, void* contex)
    	{
    		//cout << "current height is  " << height << endl;
    		Sensor* sen = (Sensor*)contex;
    		if(sen)  //注意判断sen是否有效
    			sen->getHeight(height);
    	}
    	//定义注册回调函数
    	void registCallback()
    	{
    		registHeightCallback(onHeight, this);
    	}
    	//新增的成员函数
    	void getHeight(double height)
    	{
    		cout << "current height is  " << height << endl;
    	}
    }

    如此修改之后,得到与修改前一样的效果(实时打印height),关键点在于注册回调函数的时候将Sensor对象的指针传给了contex,在回调函数中又将contex转换为Sensor对象指针,所以能调用普通函数。
    同理,如果注册时传入某一个对象的指针,就可以在回调函数中对该对象进行操作,这就是我们可以在一个对象中回调另一个对象的思想。

    回调对象

    现在开始解决之前提出的问题,本质是不变的,回调是指针传递,可以是函数指针,也可以是对象指针。

    //先定义一个类class DataPrint
    //打印数据类class DataPrint
    class DataPrint{
    public:
    	DataPrint(){}
    	~DataPrint(){}
    	void printHeight(double height)
    	{
    		cout << "print height is " << height << endl;
    	}
    }
    
    //要在类Sensor中增加DataPrint的指针和一个DataPrint指针赋值函数,class Sensor修改为
    //接收数据类class Sensor
    class Sensor{
    public:
    	Sensor(){}
    	~Sensor(){}
    	//定义回调函数onHeight
    	static void onHeight(double height, void* contex)
    	{
    		DataPrint* dp = (DataPrint*)contex;
    		if(dp)  //注意判断dp是否有效
    			dp->printHeight(height);
    	}
    	//定义注册回调函数
    	void registCallback()
    	{
    		registHeightCallback(onHeight, m_pDataPrint );
    	}
    	//新增的成员函数
    	void getHeight(double height)
    	{
    		//cout << "current height is  " << height << endl;
    	}
    	void setDataPrint(DataPrint* dp)
    	{
    		m_pDataPrint = dp;
    	}
    private:
    	DataPrint* m_pDataPrint;
    }
    
    //main主函数
    void main()
    {
    	DataPrint* dp=new DataPrint();
    	Sensor* sens=new Sensor();
    	//注意这两句的顺序不能颠倒
    	sens->setDataPrint(dp);
    	sens->registCallback();
    }

     这样就能实现在另一个类中取得回调函数的数据,如果无法保证DataPrint的实例化一定在Sensor之前,我们可以这样做

    //先定义一个类class DataPrint
    //打印数据类class DataPrint
    class DataPrint{
    public:
    	DataPrint(){}
    	~DataPrint(){}
    	void printHeight(double height)
    	{
    		cout << "print height is " << height << endl;
    	}
    }
    
    //要在类Sensor中增加DataPrint的指针和一个DataPrint指针赋值函数,class Sensor修改为
    //接收数据类class Sensor
    class Sensor{
    public:
    	Sensor(){}
    	~Sensor(){}
    	//定义回调函数onHeight
    	static void onHeight(double height, void* contex)
    	{
    		Sensor* sen= (Sensor*)contex;
    		if(sen)  //注意判断sen是否有效
    			sen->getHeight(height);
    	}
    	//定义注册回调函数
    	void registCallback()
    	{
    		registHeightCallback(onHeight, m_pDataPrint );
    	}
    	//新增的成员函数
    	void getHeight(double height)
    	{
    		if(m_pDataPrint )
    			m_pDataPrint ->printHeight(height);
    	}
    	void setDataPrint(DataPrint* dp)
    	{
    		m_pDataPrint = dp;
    	}
    private:
    	DataPrint* m_pDataPrint;
    }
    
    //main主函数
    void main()
    {
    	DataPrint* dp=new DataPrint();
    	Sensor* sens=new Sensor();
    	//注意这两句的顺序可以颠倒
    	sens->setDataPrint(dp);
    	sens->registCallback();
    }

    两个的区别是一个直接注册指定类的对象指针,另一个注册当前类的对象指针,间接调用另一个类的对象指针。

    更复杂的讨论

    刚才讨论的问题稍微复杂一点了,不过应该也容易理解,但是我们在实际项目中遇到的情况可能比这个复杂。比如在有层次的软件工程中,回调函数在底层,显示数据的类在上层,我们要如何把底层的数据显示到上层去?容易想到的是上层调用底层,如开个timer刷新,但这是不对的,你无法做到实时调用,你需要的是一个异步的机制,即底层一发生上层就能接收到。
    怎么做呢?还是一样的道理,把上层的类的对象指针传给底层,这时底层需要包含上层的头文件,但这是不对的,上层已经包含了底层的头文件,它们不能互相包含,如何解决这个问题?那就要用到C++继承的特性,首先在底层定义一个基类,然后在上层继承它,在上层实例化这个继承类后,将其指针设置给底层,底层对该指针的操作就是对继承类对象的操作,以此实现数据的传递。

    参考:

    [1] https://www.jianshu.com/p/26784d962f58

    [2] https://blog.csdn.net/weixin_40237626/article/details/82801409

    [3] https://blog.csdn.net/sinat_38183777/article/details/83958887

    [4] https://blog.csdn.net/yidu_fanchen/article/details/80513359

    展开全文
  • 微信企业号回调接口

    2015-11-08 21:13:36
    微信企业号回调接口
  • js函数的回调

    万次阅读 多人点赞 2019-07-31 19:09:41
    平常的前端开发工作中,编写js时会有很多地方用到函数的回调。 最简单的例子就是: <script language="javascript" type="text/javascript"> function doSomething(callback) { if(typeof callback == ...

    平常的前端开发工作中,编写js时会有很多地方用到函数的回调。

    最简单的例子就是:

    <script language="javascript" type="text/javascript">
    function doSomething(callback) {
    if(typeof callback == "function") {
    callback();
    }
    } 
    
    function foo() {
    alert("我是回调后执行的函数");
    } 
    
    doSomething(foo); /*正确*/
    doSomething(function(){
    alert("我是回调后执行的函数");
    }); /*正确*/
    doSomething("foo"); /* 这样是不行的,传入的是一个字符串,不是一个函数名 */
    </script>

    以上只能回调没有参数的(除法你事先知道回调的函数的参数),如果函数有未知的函数,就不能如此简单的调用了。

     

    高级方法:

    1、使用javascript的call方法

    function doSomething(callback,arg1,arg2) {
    callback.call(this,arg1,arg2);
    }
    function foo(arg1,arg2) {
    alert(arg1+":"+arg2);
    }
    doSomething(foo,1,2); /* 弹出了1:2 */

     

    2、使用javascript 的 apply方法

     

    function doSomething(callback,args) {
    callback.apply(window,args);
    }
    function foo(arg1,arg2) {
    alert(arg1+":"+arg2);
    }
    doSomething(foo,[1,2,3]); /* 弹出了1:2 */

    可以看成call和apply基本一样,区别就是call只能一个个传参数,apply只能把参数放数组里传进来

    他们的第一个参数都是作用域,比如上面传了this,表示就是和doSomething这个函数一样的作用域,当然你也可以传window,表示整个window的作用域

     

    3、apply的巧妙用法

    apply也可以看作是函数的执行函数,就是用来执行某个函数的函数。所以你会发现,有时候用好apply,有很多原本繁杂的事情会变得如此简单。

    比如数组的push方法使用apply来调用:

    var arr1=[1,3,4];

    var arr2=[3,4,5];

    如果我们要把 arr2展开,然后一个一个追加到arr1中去,最后让arr1=[1,3,4,3,4,5]

    arr1.push(arr2)显然是不行的。 因为这样做会得到[1,3,4,[3,4,5]]

    我们只能用一个循环去一个一个的push(当然也可以用arr1.concat(arr2),但是concat方法并不改变arr1本身)

    var arrLen=arr2.length

    for(var i=0;i<arrLen;i++){

        arr1.push(arr2[i]);

    }

    自从有了Apply,事情就变得如此简单

    Array.prototype.push.apply(arr1,arr2)

    一行代码就解决了,原理能看的出来,Array.prototype.push是指数组的push函数,apply(arr1,arr2)说明arr1是作用域,就等同于是arr1调用了数组的push函数,

    而且arr1的确就是个数组,所以可以调用,arr2表示入参的数组。所以,以上语句等同于:arr1.push(3,4,5)。(push函数支持传递多个入参,这也是这里可以使用apply的前提条件)

    以上语句也可以写成:arr1.push.apply(arr1,arr2); 两者完全等效,因为arr1.push表示arr1的push函数,也就是数组的push函数。

    如果使用call就是这样Array.prototype.push.call(arr1,arr2[0],arr2[1]...),显然还是apply合适。

    要是你还问,那直接用arr1.push(3,4,5)不就行了,那已经暴露了你的智商,arr2又不是不可以变,下次不是[3,4,5]了呢。

     

    还有获取数组中,最大的那个数字,也可以使用apply调用Math.max函数

    var arr1=[1,3,4];

    alert(Math.max.apply(window,arr1)); /* 作用域可以不是window,就算是null都行,Math.max.apply(this,arr1),Math.max.apply(null,arr1) */

     

    4、工作中函数回调的实际例子

    有了上面的基础,就能看的懂工作中封装好的js的回调函数了

    背景:页面A需要使用页面B来选择某个项目,然后带回这个项目的信息给页面A,页面A根据这些信息丰富自己。

    页面A:

    noticeInfo = {
    selectProject: function () {
    var win = newsee.ui.window
    win.show('项目列表', '../Project/ProjectSelectList.html?callback=noticeInfo.setProjectInfo', { size: win.winSizeType.big })
    //在当前页面弹出框,框里面是另一个页面,地址后面带上需要回调的函数名
    //注意这两个页面其实都是在一个页面里面的,并不是像window.open()那样出现了新窗口,所以两个页面的js都是可见的
    },
    setProjectInfo: function (obj) {
    //回调函数,将选择好的项目对象传进来,然后丰富自己的页面
    $('#projectName').val(obj.name)
    $('#projectID').val(obj.id)
    }
    }

    页面B:

    function SelectBack() {
    var callback = newsee.util.url.getQuery('callback'); //获取页面参数callback,这里获取到的是"noticeInfo.setProjectInfo",是个字符串
    var arr = newsee.ui.grid.getSelectedBack('datagrid') //获取选择的项目,这个不用深究
    if (!arr.length) {
    return newsee.ui.window.alert('请选择项目!')
    }
    newsee.util.url.back(callback, arr[0]) //重点来了,这里执行回调,将需要回调的函数名和入参传进来,arr[0]就是选择的项目的对象的数组了(它也是个数组,里面就一个对象)
    }

    newsee.util.url.back函数如下:

    back : function (funcName) {
    // / <param name="funcName" type="String">返回时执行的方法,一般为重新绑定</param>
    
    var isWindow = typeof $$winClose === 'function',// 是否为弹窗
    args // 弹窗返回方法参数
    
    if (isWindow) {// 弹窗的返回方法
    $$winClose()
    
    args = [].slice.call(arguments) //arguments大家应该都知道的吧,它可以用来获取函数的实参,它类似数组又不是数组,这句代码就是把它转换成数组,因为apply的入参需要是个数组才行
    //args现在里面有两个元素,args[0]=callback,就是之前传进来的回调函数名,args[1]=arr[0],就是回调函数的入参
    newsee.callFunc.apply(newsee, args) //执行 newsee.callFunc 函数,作用域就是newsee自己(等同于newsee自己调用callFunc函数),参数是args
    } 
    }

    newsee.callFunc函数如下:

    callFunc: function(funcName, arg) {
    var func = typeof funcName === 'function' ? funcName : this.findItem(window, funcName) //上面我有提到过,doSomething("foo"); 传入的是一个字符串,不是一个函数名,所以无法执行
    //同样的道理,现在funcName=args[0]=callback="noticeInfo.setProjectInfo",是个字符串,不能直接调用apply,需要变成函数
    //这句话就是用来判断funcName是不是一个函数,如果不是,就在window作用域里根据funcName找到这个函数,然后赋给func
    if (typeof func === 'function') {
    //此时func已经是个函数了,就是页面A里定义的noticeInfo.setProjectInfo()
    try {
    return func.apply(window, arg) //执行需回调的函数,作用域依然是window,反正这个函数在window里肯定能找到,参数就是arg=args[1]=arr[0],即之前在页面B获取到的项目对象
    }
    catch (e) {
    console.error(e)
    }
    }
    }

    ok,需回调的函数就这样被执行了,至于怎么根据字符串形式的函数名获取这个函数,看下面。

    //findItem函数如下:
    findItem: function(data, key) {
    // / <summary>获取对象指定键的值</summary>
    if (this.include(data, key)) { //data这里就是传进来的window,注意window就是一个对象,首先判断window对象里是否存在"noticeInfo.setProjectInfo"这个属性
    return eval('data.' + key) //如果存在,就执行"data.noticeInfo.setProjectInfo",这样就获取到了这个函数了。(eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码)
    }
    }
    //include函数如下:
    include: function(data, key) {
    // / <summary>判断对象是否存在键值</summary>
    if (data == null || typeof data !== 'object' || !key || typeof key !== 'string') {
    return false
    }
    var keys = key.split('.'),
    item = data,
    result = true
    keys.forEach(function(k) {
    if (item != null && typeof item === 'object' && k in item) {
    //依次循环遍历,第一次item = data,那就是window这个对象,k="noticeInfo",window[noticeInfo]是存在的,因为在页面A里定义了noticeInfo这么一个对象
    //第二次循环,item=window.noticeInfo,k="setProjectInfo",window.noticeInfo[setProjectInfo]也是存在的,因为在页面A里也定义了setProjectInfo这么一个函数
    //这里没有第三次循环了,所以最后返回是true,说明window对象里存在"noticeInfo.setProjectInfo"这个属性,接下来使用eval()拿到它即可
    item = item[k]
    } else {
    return result = false
    }
    })
    
    return result
    }

    对eval() 函数也介绍一下:

    eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。

    返回值就是通过计算 string 得到的值(如果有的话)。如:

    eval("x=10;y=20;document.write(x*y)") //输出 200

    document.write(eval("2+2")) //输出 4

    var x=10

    document.write(eval(x+17)) //输出 27

    所以上面的eval('data.' + key)就是执行"data.noticeInfo.setProjectInfo"这个字符串,

    因为data在这里就是指window,所以返回值就是window.noticeInfo.setProjectInfo()这个函数

     

    其实可以在简单一点,根本没必要使用eval()来获取这个函数,因为在include函数里,item就已经是window.noticeInfo.setProjectInfo这个对象了,这个对象就是我们想要的函数。

    (在js中函数也是对象,函数名就是这个函数的引用,就和地址差不多)

    既然都拿到这个函数了,直接返回不就行了,所以上面的include()和findItem可以这样简化:

    include: function(data, key) {
    if (data == null || typeof data !== 'object' || !key || typeof key !== 'string') {
    }else{
    var keys = key.split('.'),
    item = data,
    result = true
    keys.forEach(function(k) {
    if (item != null && typeof item === 'object' && k in item) {
    item = item[k]
    } else {
    result = false;
    }
    })
    if(result)
    return item
    }
    },
    findItem: function(data, key) {
    return this.include(data, key)
    }

    经过测试,发现这两个根据字符串形式的函数名获取函数的方法都可以达到一模一样的效果。

    ------------------------------------------------------------------------声明-------------------------------------------------------------
    以上部分是copy别人的,部分是自己的理解!
    本人水平有限,如有不对之处,还望大神指正,谢谢!

    展开全文
  • 微信企业号回调模式php(demo)

    热门讨论 2014-11-15 13:49:13
    回调模式下,企业不仅可以主动调用企业号接口,还可以接收用户的消息或事件。当你开启应用的回调模式时,企业号会要求你填写应用的URL、Token、EncodingAESKey三个参数。 此源码为自用已验证源码。供参考。
  • QT编写DLL给外部程序调用示例 方法 参数 返回值 事件回调 : 1:C#或者 NET 第一步:引入命名空间; using System Runtime InteropServices; 第二步:声明函数 必须与实际DLL中函数名及参数一致; [DllImport "qt...
  • C++回调函数使用心得

    万次阅读 多人点赞 2018-11-11 15:23:52
    C++回调函数使用心得前言回调函数也是普通函数C回调函数C++回调函数使用场景描述C++回调函数定义静态成员函数访问非静态成员函数的方法回调对象更复杂的讨论 前言 关于C++回调函数的介绍网上有很多,要知道它的...

    前言

    关于C++回调函数的介绍网上有很多,要知道它的概念很容易,难的是灵活应用,这里就笔者遇到的一个使用场景对回调函数进行一个简单的介绍,如果能对您有所帮助是我的荣幸。本文不会对C++回调函数的基础知识做过多的介绍,若对其概念不够理解的,笔者在此推介两篇个人认为相当优秀的博客。
    链接: link1.
    链接: link2.

    回调函数也是普通函数

    首先明确一个概念,回调函数也是普通函数,而不是什么神秘的东西。至于为什么叫回调函数,是因为程序通过参数把该函数的函数指针传递给了其它函数,在那个函数里面调用这个函数指针就相当于调用这个函数,这样的过程就叫回调,而被调用的函数就叫回调函数。看得出来,回调的本质是函数指针传递,所以想要理解回调机制,先要理解函数指针。

    C回调函数

    C++回调函数扩展自C回调函数,要想理解C++回调函数,先要理解C回调函数。我们通过一个实例来讲解C回调函数的使用方法。

    //callbackTest.c
    //1.定义函数onHeight(回调函数)
    //@onHeight 函数名
    //@height   参数
    //@contex   上下文
    void onHeight(double height, void* contex)
    {
    	sprint("current height is %lf",height);
    }
    
    //2.定义onHeight函数的原型
    //@CallbackFun 指向函数的指针类型
    //@height      回调参数,当有多个参数时,可以定义一个结构体
    //@contex      回调上下文,在C中一般传入nullptr,在C++中可传入对象指针
    typedef void (*CallbackFun)(double height, void* contex);
    
    //3.定义注册回调函数
    //@registHeightCallback 注册函数名
    //@callback             回调函数原型
    //@contex               回调上下文
    void registHeightCallback(CallbackFun callback, void* contex)
    {
    	double h=100;
    	callback(h,nullptr);
    }
    
    //4.main函数
    void main()
    {
    	//注册onHeight函数,即通过registHeightCallback的参数将onHeight函数指针
    	//传入给registHeightCallback函数,在registHeightCallback函数中调用
    	//callback就相当于调用onHeight函数。
    	registHeightCallback(onHeight,nullptr);
    }

    程序的运行结果是:
    current height is 100
    很多时候,注册的时候并不调用回调函数,而是在其他函数中调用,那我们可以定义一个CallbackFun全局指针变量,在注册的时候将函数指针赋给它,在要调用的调用它。如

    //定义全局指针变量
    CallbackFun* m_pCallback;
    //定义注册回调函数
    void registHeightCallback(CallbackFun callback, void* contex)
    {
    	m_pCallback = callback;
    }
    //定义调用函数
    void printHeightFun(double height)
    {
    	m_pCallback(height,nullptr);
    }
    //main函数
    void main()
    {
    	//注册回调函数onHeight
    	registHeightCallback(onHeight,nullptr);
    	//打印height
    	double h=99;
    	printHeightFun(99);
    }

    程序的运行结果是:
    current height is 99

    C++回调函数

    C++回调函数扩展自C,与C略有不同的是,C++可以使用全局函数和静态函数作为回调函数。考虑到全局函数会破坏封装性,所以一般都用静态成员函数。故除了理解函数指针,还要理解静态成员函数,具体一点是在静态成员函数中访问非静态成员函数的方法,因为我们很可能需要获取静态成员函数中的数据。

    使用场景描述

    比如说你使用了别人提供的sdk,这个sdk可能来自供应商,也有可能来自你的同事,他就提供给你一个注册回调函接口,比如就下面这个,你可以通过回调函数获取到height(某种传感器的实时返回的数据),你要怎么做?

    C++回调函数定义

    //CallbackFun类型
    //@CallbackFun 指向函数的指针类型
    //@height      回调参数,当有多个参数时,可以定义一个结构体
    //@contex      回调上下文,在C中一般传入nullptr,在C++中可传入对象指针
    typedef void (*CallbackFun)(double height, void* contex);
    
    //注册回调函数接口
    //@registHeightCallback 注册函数名
    //@callback             回调函数原型
    //@contex               回调上下文
    void registHeightCallback(CallbackFun callback, void* contex)

    首先,你要定义一个静态成员函数并注册。

    //sensorTest.cpp
    //接收数据类class Sensor
    class Sensor{
    public:
    	Sensor(){}
    	~Sensor(){}
    	//定义回调函数onHeight
    	static void onHeight(double height, void* contex)
    	{
    		cout << "current height is  " << height << endl;
    	}
    	//定义注册回调函数
    	void registCallback()
    	{
    		registHeightCallback(onHeight, this);
    	}
    };
    
    //main 函数
    void main()
    {
    	Sensor sens;
    	sens.registCallback();
    }

    运行程序,我们发现控制台一直在打印
    current height is **
    说明我们的回调函数正确实现了。到这一步不难,只要掌握基本的回调函数概念都能实现。
    现在我们有这样一种情况,我们有另外一个类,要在这个类里面实时打印获取的数据,要怎么做呢?

    静态成员函数访问非静态成员函数的方法

    我们知道静态成员函数中是只能出现静态变量和静态函数的,但是有些时候真的需要访问非静态成员函数或变量,比如我上面说的那种情况。让我们先来实现对同一个类中的非静态成员函数的访问。
    修改class Sensor如下

    //接收数据类class Sensor
    class Sensor{
    public:
    	Sensor(){}
    	~Sensor(){}
    	//定义回调函数onHeight
    	static void onHeight(double height, void* contex)
    	{
    		//cout << "current height is  " << height << endl;
    		Sensor* sen = (Sensor*)contex;
    		if(sen)  //注意判断sen是否有效
    			sen->getHeight(height);
    	}
    	//定义注册回调函数
    	void registCallback()
    	{
    		registHeightCallback(onHeight, this);
    	}
    	//新增的成员函数
    	void getHeight(double height)
    	{
    		cout << "current height is  " << height << endl;
    	}
    };

    如此修改之后,得到与修改前一样的效果(实时打印height),关键点在于注册回调函数的时候将Sensor对象的指针传给了contex,在回调函数中又将contex转换为Sensor对象指针,所以能调用普通函数。
    同理,如果注册时传入某一个对象的指针,就可以在回调函数中对该对象进行操作,这就是我们可以在一个对象中回调另一个对象的思想。

    回调对象

    现在开始解决之前提出的问题,本质是不变的,回调是指针传递,可以是函数指针,也可以是对象指针。

    //先定义一个类class DataPrint
    //打印数据类class DataPrint
    class DataPrint{
    public:
    	DataPrint(){}
    	~DataPrint(){}
    	void printHeight(double height)
    	{
    		cout << "print height is " << height << endl;
    	}
    };
    
    //要在类Sensor中增加DataPrint的指针和一个DataPrint指针赋值函数,class Sensor修改为
    //接收数据类class Sensor
    class Sensor{
    public:
    	Sensor(){}
    	~Sensor(){}
    	//定义回调函数onHeight
    	static void onHeight(double height, void* contex)
    	{
    		DataPrint* dp = (DataPrint*)contex;
    		if(dp)  //注意判断dp是否有效
    			dp->printHeight(height);
    	}
    	//定义注册回调函数
    	void registCallback()
    	{
    		registHeightCallback(onHeight, m_pDataPrint );
    	}
    	//新增的成员函数
    	void getHeight(double height)
    	{
    		//cout << "current height is  " << height << endl;
    	}
    	void setDataPrint(DataPrint* dp)
    	{
    		m_pDataPrint = dp;
    	}
    private:
    	DataPrint* m_pDataPrint;
    };
    
    //main主函数
    void main()
    {
    	DataPrint* dp=new DataPrint();
    	Sensor* sens=new Sensor();
    	//注意这两句的顺序不能颠倒
    	sens->setDataPrint(dp);
    	sens->registCallback();
    }

    这样就能实现在另一个类中取得回调函数的数据,如果无法保证DataPrint的实例化一定在Sensor之前,我们可以这样做

    //先定义一个类class DataPrint
    //打印数据类class DataPrint
    class DataPrint{
    public:
    	DataPrint(){}
    	~DataPrint(){}
    	void printHeight(double height)
    	{
    		cout << "print height is " << height << endl;
    	}
    };
    
    //要在类Sensor中增加DataPrint的指针和一个DataPrint指针赋值函数,class Sensor修改为
    //接收数据类class Sensor
    class Sensor{
    public:
    	Sensor(){}
    	~Sensor(){}
    	//定义回调函数onHeight
    	static void onHeight(double height, void* contex)
    	{
    		Sensor* sen= (Sensor*)contex;
    		if(sen)  //注意判断sen是否有效
    			sen->getHeight(height);
    	}
    	//定义注册回调函数
    	void registCallback()
    	{
    		registHeightCallback(onHeight, m_pDataPrint );
    	}
    	//新增的成员函数
    	void getHeight(double height)
    	{
    		if(m_pDataPrint )
    			m_pDataPrint ->printHeight(height);
    	}
    	void setDataPrint(DataPrint* dp)
    	{
    		m_pDataPrint = dp;
    	}
    private:
    	DataPrint* m_pDataPrint;
    };
    
    //main主函数
    void main()
    {
    	DataPrint* dp=new DataPrint();
    	Sensor* sens=new Sensor();
    	//注意这两句的顺序可以颠倒
    	sens->setDataPrint(dp);
    	sens->registCallback();
    }

    两个的区别是一个直接注册指定类的对象指针,另一个注册当前类的对象指针,间接调用另一个类的对象指针。

    更复杂的讨论

    刚才讨论的问题稍微复杂一点了,不过应该也容易理解,但是我们在实际项目中遇到的情况可能比这个复杂。比如在有层次的软件工程中,回调函数在底层,显示数据的类在上层,我们要如何把底层的数据显示到上层去?容易想到的是上层调用底层,如开个timer刷新,但这是不对的,你无法做到实时调用,你需要的是一个异步的机制,即底层一发生上层就能接收到。
    怎么做呢?还是一样的道理,把上层的类的对象指针传给底层,这时底层需要包含上层的头文件,但这是不对的,上层已经包含了底层的头文件,它们不能互相包含,如何解决这个问题?那就要用到C++继承的特性,首先在底层定义一个基类,然后在上层继承它,在上层实例化这个继承类后,将其指针设置给底层,底层对该指针的操作就是对继承类对象的操作,以此实现数据的传递。
    这里就不贴代码了,思想是这样的,很多情况下需要实际问题实际分析,欢迎讨论。

    展开全文
  • c语言回调函数的使用及实际作用详解

    千次阅读 多人点赞 2021-07-16 23:49:20
    回调函数这个知识点其实并不是很难,难是难在网上很多讲解回调函数的都说的太学术化了化了,一点也不亲民。 很多人即使知道怎么写回调函数也根本就搞不懂它们在实际产品中也有什么用,什么时候用。 所以这节课呢...

    大家好,我是无际。

    今天给大家讲一下芯片/模块厂家写SDK必须会使用的一种技术:回调函数。

    回调函数这个知识点其实并不是很难,难是难在网上很多讲解回调函数的都说的太学术化了化了,一点也不亲民。

    很多人即使知道怎么写回调函数也根本就搞不懂它们在实际产品中也有什么用,什么时候用。

    所以这节课呢我们会以程序架构的需求为出发点,讲解回调函数是怎么满足它这个需求的。

    为了方便大家理解,这篇内容也对应有一篇文章,大家可以找无际单片机编程获取。

    一、通过这节课程你能掌握以下知识:

    1. 掌握程序架构的核心理念或需求。
    2. 掌握回调函数的作用
    3. 掌握回调函数的程序编写
    4. 掌握回调函数在产品中的应用

    二、程序架构的核心理念和需求

    很多人可能会说一个好的程序架构啊,就是代码很紧凑、执行效率也很高。

    其实这个说的很片面,不完全对,这只能说明你程序算法写的好,但架构不一定做的好。

    即然是架构,那自然是以从”大局”为重,思维不能局限于当下的产品功能,还要考虑到以后功能的增加和裁剪,那么对于单片机开发来说,我认为一个好的程序架构至少要达到以下要求:

    硬件层和应用层的程序代码分开,相互之间的控制和通讯使用接口,而且不会共享的全局变量或数组。

    这里呢,我就这个要求,别小看这一个要求,因为这个要求里面蕴藏着很多学问的,比如用专业称为可移植性、可扩展性。

    那么我们来想象一下我们通常写单片机代码的方式啊,在51的时候基本一个.c文件解决,包括寄存器配置啊,产品功能啊。

    这种就是没有架构的程序,然后我们进化到STM32这个单片机以后,程序大了,慢慢也会在工程文件里加几个文件夹目录把硬件层和应用层代码分开了。

    于是我们会把一些不同的外设功能,比如Led、按键、串口等外设功能代码分别写在不同的.c文件里,然后统一用函数接口去调用它。

    比方说控制一个LED灯亮,直接在led.c文件里写一个驱动led灯状态的函数然后给外部调用就好了。

    那我们我们看这种Led的控制函数确实也是满足程序架构的需求的,硬件层和应用层代码分开,应用层用硬件层提供的接口来控制,而且又不会有硬件层和应用层共享的全部变量或数组。像这种是不是很简单?

    那么不知道你们有没有碰到另外一种情况,就是应用程序需要采集硬件层的数据,比如串口接收数据,按键采集、ADC值采集。

    这种硬件层的数据怎么通知应用层来拿,或者怎么主动给它?

    我们以往最简单粗暴的方式是不是就是用一个全局变量,比方说硬件层串口接收到数据来了,那么我们把数据丢到数组里,然后把接收完成全局变量标志位置1。

    比方说全局变量名为RcvFlag,然后应用层程序会轮询判断RcvFlag==1?是的话就开始把数组里的数据取出来解析。

    很多人就会说了,你看我用这种方法照样能实现功能啊,为什么还要学习别的架构。

    这样做当然可以实现功能,但是会存在移植性很差的问题。

    比如说你们老板让你把这个串口的硬件层封装起来给客户用,但不能让客户看到你实现的源代码,只提供接口(函数名)给对方用。

    那么这时候难道你要告诉客户先判断哪个变量为1,然后再取哪个数组的数据这么LOW的做法吗?

    那么如果是懂行的客户一定会怀疑你们公司的技术实力是不是小学生水平。

    那怎样做才会既方便又专业呢? 这里我们就需要用到回调函数啦。

    三、回调函数的作用

    那么在讲回调函数之前呢,对于函数调用呢我一般分为2种类型:

    1.输出型

    不知道大家有没有用过C语言自带的一些库函数,比如说sizeof()获取数据长度的函数,memcpy()是内存拷贝函数,我们调用这个函数之后呢就能完成相应的功能。

    还有我们基于单片机的一些程序函数,比方说控制LED点亮熄灭、继电器吸合断开、LCD驱动等等。

    那么这些呢,我一般称为输出型的函数。

    输出型函数我们是主导的角色,我们知道什么时候该调用它。

    2.输入型

    输入型呢,也称为的是响应式的函数

    什么叫响应式的函数呢?

    比方说接收串口的数据,我们不知道什么数据什么时候来。

    再比方说,我们按键检测的函数,我们不知道什么时候会按下按键,那么这些就要定义成响应式函数来实现,而响应式函数就可以用回调函数来实现

    所以通过这两个种类型的分析啊,我们就可以知道,回调函数基本是用在输入型的处理中。

    比方说串口数据接收,那么数据是输入到单片机里面的,单片机是处于从机角色。

    按键检测,按键状态是输入到单片机里的。

    再比方说ADC值采集,ADC值也是输入到单片机里的。

    那么它们输入的时间节点都是未知的,这些就能够用回调函数来处理。

    具体怎么处理后面我们会用代码来给大家举例。

    回调函数还有一个作用就是为了封装代码

    比如说做芯片或者模组的厂家,我们拿典型的STM32来举例,像外部中断、定时器、串口等中断函数都是属于回调函数,这种函数的目的是把采集到的数据传递给用户,或者说应用层。

    所以回调函数的核心作用是:

    1.把数据从一个.c文件传递到另一个.c文件,而不用全局变量共享数据这么LOW的方法。

    2.对于这种数据传递方式,回调函数更利于代码的封装。

    四、掌握回调函数的程序编写

    前面说了很多概念性的东西,可能大家也比较难理解,回调函数最终呢是靠函数指针来实现的。

    那么我这里通过一些模拟按键的例子来演示下怎么回通过调函数来处理它们。

    下面是我们的c-free工程,用这个来模拟方便点:

    从模块化编程的思想来看,整个工程分为2个部分,应用层main.c文件,硬件层key.c和key.h文件。

    不管再怎么复杂的程序,我们都要先从main函数一步步往下挖,main函数代码如下。

    int main(int argc, char *argv[])
    {
    KeyInit();
    KeyScanCBSRegister(KeyScanHandle);
    KeyPoll();
    
    return 0;
    }

    KeyInit();是key.c文件的按键初始化函数

    KeyScanCBSRegister(KeyScanHandle);是key.c的函数指针注册函数。

    这个函数可能大家会有点蒙,请跟进我们的节奏,下面开始烧脑环节,也是写回调函数的必须步骤,

    想理解这个回调函数注册函数,我们要先从硬件层(key.h)头文件的函数指针定义说起,具体看下图。

    这里自定义了一个函数指针类型,带两个形参。

    然后,我们在key.c这个文件里定义了一个函数指针变量。

    重点来了,我们就是通过这个函数指针,指向应用层的函数地址(函数名)

    具体怎么实现指向呢?就是通过函数指针注册函数。

    这个函数是在main函数里调用,使用这种注册函数的方式注册灵活性也很高,你想要在哪个.c文件使用按键功能就在哪里调用。

    这里要注意,main.c这个文件要定义一个函数来接收硬件层(key.c)过来的数据。

    这里定义也不是乱定义的,一定要和那个自定义函数指针类型返回值、形参一致。

    然后把这个函数名字直接复制给KeyScanCBSRegister函数的形参就可以了。

    这样调用后,我们key.c文件的pKeyScanCBS这个指针其实就是指向的KeyScanHandle函数。

    也就是说执行pKeyScanCBS的时候,就是执行KeyScanHandle函数。

    那具体检测按键的功能就是KeyPoll函数,这个在main函数里调用。

    当检测到键盘有输入以后,最终会调用pKeyScanCBS。

    最终执行的是main.c文件的KeyScanHandle函数。

    所以,我们来看下输出结果。

    如果还是有点模糊,下面我再给大家捋一捋编写和使用回调函数的流程:

    1. 自定义函数指针,形参作为硬件层要传到应用层的数据。
    2. 硬件层定义一个函数指针和函数指针注册函数。
    3. 应用层定义一个函数,返回值和形参都要和函数指针一致。
    4. 应用层调用函数指针注册函数,把定义好的函数名称作为形参传入。

    Ok,这就是回调函数的使用。

    如果还看不懂建议多看两遍。

    下面请大家思考一下,这个程序虽然简单,但是不是架构还不错?应用层和硬件层完全独立?

    展开全文
  • 一、如何在一个callback回调函数中调用另一个回调函数   网上找了好多帖子,都是在答非所问,我最终失去了耐心,自己去写个小demo碰碰运气吧,然后非常幸运,我解决了,哈哈,看下面的小案例。 图形界面非常简单,...
  • 一文告诉你什么是回调地狱,如何解决回调地狱?

    千次阅读 多人点赞 2020-12-13 17:17:40
    文章目录前言一、回调地狱是什么?二、如何解决回调地狱1.Promise2.async/await总结 前言 在正式了解“回调地狱”之前,我们先了解两个概念: 回调函数 当一个函数作为参数传入另一个参数中,并且它不会立即执行,...
  • 钉钉事件回调服务端回调方法编写

    千次阅读 2020-05-23 15:58:31
    /** * 创建应用,验证回调URL创建有效事件(第一次保存回调URL之前) */ private static final String EVENT_CHECK_CREATE_SUITE_URL = "check_create_suite_url"; /** * 创建应用,验证回调URL变更有效事件(第一...
  • 实现文件上传,以及表单提交成功的回调函数
  • 深入理解:回调函数

    万次阅读 多人点赞 2019-06-21 15:36:09
    关于回调函数到底是什么,已经困扰了我很久了~ 在知乎上看到几位大神的帖子,才恍然大悟 作者:no.body 链接:https://www.zhihu.com/question/19801131/answer/27459821 来源:知乎 作者:常溪玲 链接...
  • 回调函数 同步回调 异步回调

    千次阅读 2018-06-11 16:56:34
    回调函数一般是在封装接口的时候,回调显得特别重要,我们首先假设有两个程序员在写代码,A程序员写底层驱动接口,B程序员写上层应用程序,然而此时底层驱动接口A有一个数据d需要传输给B,此时有两种方式: ...
  • 异步回调与同步回调

    万次阅读 2018-05-22 19:13:35
    同步回调 我们常用的一些请求都是同步回调的,同步回调是阻塞的,单个的线程需要等待结果的返回才能继续执行。异步回调 有的时候,我们不希望程序在某个执行方法上一直阻塞,需要先执行后续的方法,那就是这里的...
  • Java接口回调

    千次阅读 2020-01-03 13:48:30
    回调的含义和用途 什么是回调? 一般来说,模块之间都存在一定的调用关系,从调用方式上看,可以分为三类:同步调用、异步调用和回调。同步调用是一种阻塞式调用,即在函数A的函数体里通过书写函数B的函数名来调用...
  • 钉钉开发之业务事件回调

    千次阅读 2019-11-26 00:35:04
    一、钉钉开发之业务事件回调 1.注册业务事件回调接口 ①、微应用服务器调用 注册事件回调接口(post请求) https://oapi.dingtalk.com/call_back/register_call_back?access_token=ACCESS_TOKEN 请求参数示例: { ...
  • 1. 回调函数: 函数指针的调用,即是一个通过函数指针调用的函数; 如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。 In computer programming, ...
  • VC++ DLL 实现回调函数的实例

    热门讨论 2011-12-28 19:35:28
    VC 程序传函数到DLL里实现回调函数的实例。一个简单的例子。可以举一反三。
  • 异步实现:回调回调和消息队列

    千次阅读 2019-04-01 20:13:35
    异步实现方式一:异步回调 异步回调的实现依赖于多线程或者多进程 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。 同步调用是一种阻塞式调用,调用方要等待对方...
  • 浅谈C++回调函数

    千次阅读 2018-02-28 22:09:30
    1.什么是回调函数? 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方...
  • 回调函数到底有什么好处

    千次阅读 2020-10-24 18:59:17
    在最开始接触到"回调函数"这个概念的时候,自己一直都没能理解"回调函数"的优点。感觉自己写的方法很少用这种概念,可是又不理解为什么php或者js当中,很多内置函数都用了回调的思想。下面将以一个通俗的事例,来为...
  • JNI 接口回调

    千次阅读 2019-01-24 22:27:06
    JNI 接口回调 这里主要演示从 Java 层传入自定义listener,然后由 c/c++ 层在某一时期某一线程主动调用 listener 的回调函数,完成异步回调的功能。 关于 jni 的其他部分基础知识本文不做详细介绍。 Java 层定义代码...
  • 异步实现方式一:异步回调

    万次阅读 多人点赞 2018-03-21 18:07:30
    异步回调的实现依赖于多线程或者多进程软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向...
  • C语言中函数指针和回调函数的详解

    万次阅读 多人点赞 2019-05-18 23:10:01
    谈完回调函数的意义,我们就有了用户和开发者之间的概念,举个例子,用户是实现myfun这个函数,开发者是实现rt_data函数,根据需求用户将myfun函数以参数的形式传入开发者的rt_data函数中,rt_data函数就能返回给...
  • 企业微信外部联系人回调事件

    千次阅读 2019-02-22 10:20:22
    企业微信外部联系人回调事件 说明: 1) 下列&amp;quot;外部联系人&amp;quot; 和 &amp;quot;客户联系&amp;quot; 其实都是一个意思,都是指顾客,但是由于企业微信开发文档中叫&amp;quot;外部联系人&...
  • 纯js弹出层layer跨Iframe完美回调

    热门讨论 2014-12-08 11:01:01
    适用小巧的纯js弹出层插件,具体见http://blog.csdn.net/luoyehanfei/article/details/41799969
  • 看了就懂的Promise和回调函数

    千次阅读 2020-04-08 17:59:47
    最通俗易懂的回调函数 (callback)与Promise
  • 一文搞懂C语言回调函数

    万次阅读 多人点赞 2019-07-09 00:40:58
    什么是回调函数 我们先来看看百度百科是如何定义回调函数的: 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我...
  • matlab串口收发及回调函数编程

    热门讨论 2011-08-20 16:38:27
    matlab创建com对象。并采用中断方式响应回调函数,功能完整,包括创建初始化及关闭销毁。回调函数的格式,实现方法。
  • 回调函数详解

    千次阅读 2018-12-04 19:26:53
    一、什么是回调函数   回调函数是指 使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。函数是你...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,274,936
精华内容 509,974
关键字:

回调