回调函数

javascript异步编程

自古美人都是妖i 提交于 2020-02-06 05:22:19
你可能知道,Javascript语言的执行环境是"单线程"(single thread)。 所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。 这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。 为了解决这个问题,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。 "同步模式"就是上一段的模式,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的;"异步模式"则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。 "异步模式"非常重要。在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作。在服务器端,"异步模式"甚至是唯一的模式,因为执行环境是单线程的,如果允许同步执行所有http请求

【1/33】调用堆栈

你说的曾经没有我的故事 提交于 2020-02-06 03:44:46
33 文章目录 调用栈 JavaScript 引擎 执行上下文 创建执行上下文 变量环境: 执行阶段 javascript事件循环 setTimeout setInterval Promise与process.nextTick(callback) 调用栈 调用栈 是解释器(就像浏览器中的JavaScript解释器)追踪函数执行流的一种机制。当执行环境中调用了多个函数函数时,通过这种机制,我们能够追踪到哪个函数正在执行,执行的函数体中又调用了哪个函数。 拥有 LIFO(后进先出)数据结构的栈,被用来存储代码运行时创建的所有执行上下文。 当 JavaScript 引擎第一次遇到你的脚本时,它会创建一个全局的执行上下文并且压入当前执行栈。每当引擎遇到一个函数调用,它会为该函数创建一个新的执行上下文并压入栈的顶部。 每调用一个函数,解释器就会把该函数添加进调用栈并开始执行。每一个进入调用栈的都称为 调用帧 。 正在调用栈中执行的函数还调用了其它函数,那么新函数也将会被添加进调用栈,一旦这个函数被调用,便会立即执行。 当前函数执行完毕后,解释器将其清出调用栈,继续执行当前执行环境下的剩余的代码。 当分配的调用栈空间被占满时,会引发 堆栈溢出 。 JavaScript 引擎 谷歌的 V8 引擎: 在这里插入代码片 这个引擎主要由两部分组成: 内存堆:这是内存分配发生的地方 调用栈

Windows线程池函数

我的梦境 提交于 2020-02-04 22:36:41
Windows提供给了一个与 完成端口 相配套的线程池机制。 1.以异步的方式调用函数 //工作项 2.每隔一段时间调用一个函数 //计时项 3.在内核对象触发的时候调用一个函数 //等待项 4.在异步I/O请求完成的时候调用一个函数 //I/O项 1.以异步的方式调用函数 创建一个工作项,分多次提交任务。 PTP_WORK CreateThreadpoolWork(PTP_WORK_CALLBACK pfnWorkHandler,PVOID pvContext,PTP_CALLBACK_ENVIRON pcbe); pvContext:传给回调函数的值 pcbe:和线程池的定制有关 pfnWorkHandler:函数指针,该函数的函数原型这个样子 VIOD CALLBACK WorkCallBack(PTP_CALLBACK_INSTANCE Instance,PVOID Context,PTP_WORK Work);//Work:创建函数的返回值 向线程池提交一个任务请求: VOID SubmitThreadpoolWork(PTP_WORK Work); 如果需要多次提交一个工作项,每次回调函数执行的时候,传入的Context的值肯定是相同的。 在另一个线程中,想要取消或者等待工作项处理完毕然后将线程挂起: VOID

说说JSONP

青春壹個敷衍的年華 提交于 2020-02-04 08:27:18
1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准; 2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>); 3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理; 4、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据; 5、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。 6、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。 7、为了便于客户端使用数据,逐渐形成了一种非正式传输协议

Node.js入门:异步IO

好久不见. 提交于 2020-02-04 07:59:17
异步IO 在操作系统中,程序运行的空间分为内核空间和用户空间。我们常常提起的异步I/O,其实质是用户空间中的程序不用依赖内核空间中的I/O操作实际完成,即可进行后续任务。 同步IO的并行模式 多线程单进程 多线程的设计之处就是为了在共享的程序空间中,实现并行处理任务,从而达到充分利用CPU的效果。多线程的缺点在于执行时上下文交换的开销较大,和状态同步(锁)的问题。同样它也使得程序的编写和调用复杂化。 单线程多进程 为了避免多线程造成的使用不便问题,有的语言选择了单线程保持调用简单化,采用启动多进程的方式来达到充分利用CPU和提升总体的并行处理能力。它的缺点在于业务逻辑复杂时(涉及多个I/O调用),因为业务逻辑不能分布到多个进程之间,事务处理时长要远远大于多线程模式。 异步IO的必要性 采用同步方式的程序要完成这两个任务的时间总花销会是m + n。但是如果是采用异步方式的程序,在两种I/O可以并行的状况下(比如网络I/O与文件I/O),时间开销将会减小为max(m, n)。而当并行任务更多的时候,m + n + …与max(m, n, …)之间的孰优孰劣更是一目了然。Node.js天然地支持这种异步I/O,这是众多云计算厂商对其青睐的根本原因。 操作系统对异步I/O的支持 异步与非阻塞听起来似乎是同一回事。从实际效果的角度说,异步和非阻塞都达到了我们并行I/O的目的

Nodejs之路:异步I/O的过程

好久不见. 提交于 2020-02-04 07:58:27
对于Node中的异步I/O调用,从发出调用到回调执行,看起来像普通的js异步,但是流程却和普通js那些消息队列完全不同,整个过程经历了哪些? 下面以Windows平台下为例: 一,异步调用第一阶段: 1,首先JavaScript调用Node的核心模块,核心模块再调用C++内建模块,内建模块通过libuv进行系统调用。(这里的libuv是抽象封装层,使得平台兼容性的判断都由这一层来实现,并保证上层的Node与下层的自定义线程及IOCP之间互相独立。Node在编译期间会判断平台条件,选择性编译unix目录或是win目录下的源文件到目标程序中。) 内建模块调用过程中,会创建一个FSReqWrap 请求对象 ,从JavaScript层传入的参数和当前方法都被封装在这个请求对象中,而回调函数则被设置在这个请求对象的oncomplete_sym属性上。 2,对象包装完毕后,在Windows下,则调用QueueUserWorkItem()方法将这个FSReqWrap请求对象推入线程池中等待执行,该方法使用代码如下: QueueUserWorkItem( &uv_fs_thread_proc, req, WT_EXECUTEDEFAULT ) 这个方法接收三个参数,第一个是将要执行的方法的引用,这里的例子是uv_fs_thread_proc, 这里实际上就是要执行的I/O操作实际对应的方法

Node.js 之 HTTP实现详细分析

我的梦境 提交于 2020-02-04 07:45:58
分针网每日分享:Node.js 之 HTTP实现详细分析 Node.js的强项是处理网络请求,那我们就来分析一个HTTP请求在Node.js中是怎么被处理的,以及JavaScript在这个过程中引入的开销到底有多大。 Node.js采用的网络请求处理模型是IO多路复用。它与传统的主从多线程并发模型是有区别的:只使用有限的线程数(1个),所以占用系统资源很少;操作系统级的异步IO支持,可以减少用户态/内核态切换,并且本身性能更高(因为直接与网卡驱动交互);JavaScript天生具有保护程序执行现场的能力(闭包),传统模型要么依赖应用程序自己保存现场,或者依赖线程切换时自动完成。当然,并不能说IO多路复用就是最好的并发模型,关键还是看应用场景。 我们来看“hello world”版Node.js网络服务器: require ( 'http' ) . createServer ( (req , res ) = > { res . end ( 'hello world' ) ; } ) . listen ( 3333 ) ; 代码思路分析 createServer([requestListener]) createServer创建了http.Server对象,它继承自net.Server。事实上,HTTP协议确实是基于TCP协议实现的

[原]tornado源码分析系列(五)[HTTPServer 层]

狂风中的少年 提交于 2020-02-04 07:44:31
引言:第四章讲解的有些乱,主要是代码太长了,而且还是在一章就讲完了,所以我决定将IOStream上层的HTTPServer类分作几章来讲,不按照代码顺序 在讲完了IOLoop和IOStream后就知道,第一次在监听套接口的时候需要用到IOLoop,然后创建一个IOStream对象,然后以后的IO操作都由IOStream对象完成 所以在上层的HTTP协议处理中,tornado定义了一个HTTPConnection类 这个类主要完成的工作就是完成对下,完成HTTP数据包的传输,对上层HTTPserver提供解析后的request对象 那么他们之间的工作模式是怎样的呢 看看Demo import httpserver import ioloop def handle_request(request): message = "You requested %s\n" % request.uri request.write("HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s" % ( len(message), message)) request.finish() http_server = httpserver.HTTPServer(handle_request) http_server.listen(8888) ioloop.IOLoop

微信小程序:自定义回调函数(callback)

徘徊边缘 提交于 2020-02-04 07:26:01
使用场景 自定义了一个方法getNameAndCount(),用于向后台发送请求,获取数据库里的一些数据在页面打开的时候就显示在页面上。 /** * 生命周期函数--监听页面加载 * 一个页面只会调用一次 */ onLoad : function ( options ) { this . data . openid = app . globalData . openid this . data . requestUrl = app . globalData . requestUrl // 获取所有调味品和菜品的数量 this . getNameAndCount ( ) ; } , 如上所示,由于onLoad()是生命周期函数,在页面加载的时候就会执行,在Page.onLoad()中调用getNameAndCount()就会使得页面显示的时候已经获取到了想要的值。 但由于 getNameAndCount() 是网络请求,可能会在 Page.onLoad 之后才返回,出现页面显示值为空的情况(实际上已经从后台获取到了值)。 解决方法 如下所示,就需要在getNameAndCount()中自定义一个回调函数(getNameAndCount())。 getNameAndCount : function ( ) { // ... wx . request ( { // ... // 请求成功

JavaScript中Array

醉酒当歌 提交于 2020-02-04 02:48:07
一,针对于数组 const arr = ['a','b','c','d']; Array.indexOf 将“返回第一次出现给定元素的索引”; console.log(arr.indexOf('b')); // 1 Array.includes 只想知道数组是否包含某个值;布尔值 console.log(arr.includes('c')); // true 二,针对于数组对象 const objArr = [ { id: 1, name: 'a' }, { id: 2, name: 'b' }, { id: 3, name: 'c' }, { id: 4, name: 'd' }, { id: 5, name: 'b' }, ] function getObj (name) { return objArr => objArr.name===name; } Array.filter 返回一个新的数组,过滤,它接受一个回调函数作为参数,基于一个包含所有元素的数组创建出一个新的数组。遍历整个数组; console.log(objArr.filter(getObj('b'))); // [{ id: 2, name: 'b' },{ id: 5, name: 'b' }] Array.find 返回一个元素值,只要找到第一个满足回调函数的元素,Array.find 就会停止