异步 *** 作和事件循环机制(Event Loop)

异步 *** 作和事件循环机制(Event Loop),第1张

JavaScript 运行时,除了一个正在运行的主线程,引擎还提供一个任务队列(task queue),里面是各种需要当前程序处理的异步任务。(实际上,根据异步任务的类型,存在多个任务队列。为了方便理解,这里假设只存在一个队列。)

首先,主线程会去执行所有的同步任务。等到同步任务全部执行完,就会去看任务队列里面的异步任务。如果满足条件,那么异步任务就重新进入主线程开始执行,这时它就变成同步任务了。等到执行完,下一个异步任务再进入主线程开始执行。一旦任务队列清空,程序就结束执行。

异步任务的写法通常是回调函数。一旦异步任务重新进入主线程,就会执行对应的回调函数。如果一个异步任务没有回调函数,就不会进入任务队列,也就是说,不会重新进入主线程,因为没有用回调函数指定下一步的 *** 作。

JavaScript 引擎怎么知道异步任务有没有结果,能不能进入主线程呢? 答案就是引擎在不停地检查,一遍又一遍,只要同步任务执行完了,引擎就会去检查那些挂起来的异步任务,是不是可以进入主线程了。这种循环检查的机制,就叫做 事件循环(Event Loop) 。 维基百科 的定义是:“事件循环是一个程序结构,用于等待和发送消息和事件(a programming construct that waits for and dispatches events or messages in a program)”。

什么是回调函数

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

  理解回调函数!

  程序在调用一个函数(function)时(通常指api)相当于程序(program)呼叫(Call)了一个函数(function)关系表示如下:

  call(调用)

  program --------------------→ dll

  程序在调用一个函数时,将自己的函数的地址作为参数传递给程序调用的函数时(那么这个自己的函数称回调函数)需要回调函数的 DLL 函数往往是一些必须重复执行某些 *** 作的函数关系表示如下:

  call(调用)

  program --------------------→ dll

  ↑ ¦

  ¦_______________________________¦

  callback(回调)

  当你调用的函数在传递返回值给回调函数时,你就可以利用回调函数来处理或完成一定的 *** 作。至于如何定义自己的回调函数,跟具体使用的API函数有关,很多不同类别的回调函数有各种各样的参数,有关这些参数的描述一般在帮助中有说明回调函数的参数和返回值等其实简单说回调函数就是你所写的函数满足一定条件后,被DLL调用!

  也有这样的说法(比较容易理解):

  回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。为此,你需要做三件事:

  1 声明;

  2 定义;

  3 设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于DLL调用。

callback这个词本意是打电话对方不在,通过某种方法让那个人在的时候给你打回来。

void f() { } 调用这个函数话和回调没有任何关系。就相当于A:"B,你去干f。"

void f(int (g)()) { g(); } 这个函数就带有回调的特征。调用的时候好像 A:"B,你去干f。干好了叫我干g。"

也就是调用方留一个让被调用方在特定时候通知他的线索,对他进行“回调”。

----

接着上面说,f这个工作要求是干完以后干一件事g。但是这个g并不是f自己规定的,是在调用f的时候再告诉f的。比如你可以让B在完成的时候,什么也不干;或者叫你一声;或者让你干另外一件事。就是说g这个工作本身就是个变量。

----

如果不作为参数提供,g就成了f固定的一部分。A直接说“你去干f”不就是了。作为参数的意义就在于,这个g可以随意改变。

----

基本上不可能有书会去具体讲回调函数。回调只是一个很基本的函数指针的使用。

你这写法根本都不对,EndInvoke怎么写到回调函数里去了

判断执行完不需要while循环判断,直接执行EndInvoke最自动阻塞,EndInvoke的参数里就有返回值可以解决你这问题

仔细看看:

http://msdnmicrosoftcom/zh-cn/library/2e08f6ycaspx

所谓回调,就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数。例如Win32下的窗口过程函数就是一个典型的回调函数。一般说来,C不会自己调用B,C提供B的目的就是让S来调用它,而且是C不得不提供。由于S并不知道C提供的B姓甚名谁,所以S会约定B的接口规范(函数原型),然后由C提前通过S的一个函数R告诉S自己将要使用B函数,这个过程称为回调函数的注册,R称为注册函数。Web Service以及Java的RMI都用到回调机制,可以访问远程服务器程序。

下面举个通俗的例子:

某天,我打电话向你请教问题,当然是个难题,^_^,你一时想不出解决方法,我又不能拿着电话在那里傻等,于是我们约定:等你想出办法后打手机通知我,这样,我就挂掉电话办其它事情去了。过了XX分钟,我的手机响了,你兴高采烈的说问题已经搞定,应该如此这般处理。故事到此结束。这个例子说明了“异步+回调”的编程模式。其中,你后来打手机告诉我结果便是一个“回调”过程;我的手机号码必须在以前告诉你,这便是注册回调函数;我的手机号码应该有效并且手机能够接收到你的呼叫,这是回调函数必须符合接口规范。

通过上面个人感觉到回调更多的应用就是结合异步。比如:Ajax中js通过组件和服务器的异步通信。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/12188985.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存