JavaScript异步编程(一) 深入理解JavaScript事件

JavaScript异步编程

深入理解JavaScript事件

?事件的调度

JavaScript事件处理器在线程空闲之前不会运行

线程的阻塞

var start = new Date();

// setTimeout和setInterval的计时精度比期望值差

setTimeout(function(){

         var end = new Date();

         console.log(‘Time elapsed‘, end - start, ‘ms‘);

}, 500);

while(new Date - start < 1000) {};

结果上看出setTimeout没有使用另一线程

队列

调用setTimeout时,会有一个延时事件排入队列;

输入事件的工作方式完全一样,如单机事件发生时,会有一个单击事件排入队列。但是,单击事件处理器要等到当前所有正在运行的代码均结束后才会执行。

?异步函数类型

两大类:I/O函数和计时函数

异步的I/O函数

Node.js的出现是为了建立一个在某高级语言之上的事件驱动型服务器框架。

JavaScript语言可以完美地实现非阻塞式I/O。

如:

var ajaxRequest = new XMLRequest();

ajaxRequest.open(‘GET’, url);

ajaxRequest.send(null);

// 只需要附加一个事件处理器,随即返回事件队列

ajaxRequest.onreadystatechange = function() {

// …

}

因此,开发者需要做的只是定义一个回调就可以了。

WebKit的console.log是异步的吗?

  var a = {name: ‘1‘};

  console.log(a);

  a.name = ‘2‘;

  console.log(a);

执行后打开控制台结果:

先打开控制台,然后再执行的结果:

原因:

Console是浏览器的控制台所提供的对象,只有在控制台打开时才起作用;

console.log并没有立即拍摄对象快照,只是存储了一个对象的引用;

异步的计时函数

可能为了作动画或模拟;

setTimeout与setInterval(不精确的计时工具)

以上两个函数的缺陷:即使时延设置为0,在浏览器中的执行频率也大约为200次/秒;

原因:HTML规范推行的延时/时隔最小值为4毫秒;

需要更细粒度计时的方案:requestAnimationFrame函数

?异步函数的编写

任何函数只要使用了异步的函数,从上到下都是异步的。

异步函数的特性:非阻塞

非阻塞强调了异步函数的高速度

间或异步的函数

有些函数某些时候是异步的,但其他时候却不然;

例:jQuery的同名函数可用于延迟函数直到DOM已经结束加载;

但DOM如果早已结束了加载,则不存在任何延迟,$的回调将会立即触发;

// application.js

$(function() {

utils.log(‘Ready‘);

});

// utils.js

window.utils = {

log: function() {

if(window.console)

console.log.apply(console, arguments);

}

};

<script src="application.js" type="text/javascript"> </script>

<script src="utils.js" type="text/javascript"> </script>

这段代码运行得很好,但前提是浏览器并未从缓存中加载页面(这会导致DOM 早在脚本运行之前就已加载就绪)。如果出现这种情况,传递给$的回调就会在设置utils.log 之前运行,从而导致一个错误。

缓存型异步函数

function runCalculation(formula, callback) {

if (formula in calculationCache) {

return callback(calculationCache[formula]);

};

if (formula in calculationCallbacks) {

return setTimeout(function() {

runCalculation(formula, callback);

}, 0);

};

mathWorker.postMessage(formula);

calculationCallbacks[formula] = callback;

}

公式已经计算完成,于是结果位于calculationCache 中。这种情况下,runCalculation 是同步的。

公式已经发送给Worker 对象,但尚未收到结果。这种情况下,runCalculation 设定了一个延时以便再次调用自身;重复这一过程直到结果位于calculationCache 中为止。

异步递归与回调存储

避免异步递归,尽量采用回调存储。

返值与回调

永远不要定义一个潜在同步而返值却有可能用于回调的函数。

避免使用计时器方法来等待某个会变化的东西。如果同一个函数既返值又运行回调,则请确保回调在返值之后才运行。

?异步错误的处理

大多数JavaScript环境会提供一个有用的堆栈轨迹。

回调内抛出的错误

setTimeout(function A() {
    setTimeout(function B() {
        setTimeout(function C() {
            throw new Error(‘Something terrible has happened!‘);
        }, 0);
      }, 0);
}, 0);

 A和B并未出现在堆栈轨迹中,因为这三个函数都是从事件队列直接运行的;

同理,try/catch语句块不能捕获从异步回调中抛出的错误;

要记住的是,只能在回调内部处理源于回调的异步错误。

windows.onerror 处理器返回true,能阻止浏览器的默认错误处理行为。

避免两层以上的函数嵌套。关键是找到一种在激活异步调用之函数的外部存储异步结果的方式,这样回调本身就没有必要再嵌套了。

时间: 2024-12-27 21:41:01

JavaScript异步编程(一) 深入理解JavaScript事件的相关文章

JavaScript异步编程(二) 分布式事件

分布式事件 发布/订阅模式分发事件 ?PubSub模式 浏览器允许向DOM元素附加事件处理器: Node的EventEmitter对象 emitter.on('evacuate', function() {-}); emitter.emit('evacuate'); emit意为触发,负责调用给定事件类型的所有处理器 创建自己的PubSub PubSub.on = function(eventType, handler) { if(!(eventType in this.handlers)) {

探索Javascript异步编程

异步编程带来的问题在客户端Javascript中并不明显,但随着服务器端Javascript越来越广的被使用,大量的异步IO操作使得该问题变得明显.许多不同的方法都可以解决这个问题,本文讨论了一些方法,但并不深入.大家需要根据自己的情况选择一个适于自己的方法. 笔者在之前的一片博客中简单的讨论了Python和Javascript的异同,其实作为一种编程语言Javascript的异步编程是一个非常值得讨论的有趣话题. JavaScript 异步编程简介 回调函数和异步执行 所谓的异步指的是函数的调

Javascript异步编程方法之------“事件监听”

Javascript异步编程方法之------“事件监听”另一种思路是采用事件驱动模式.任务的执行不取决于代码的顺序,而取决于某个事件是否发生.还是以f1和f2为例.首先,为f1绑定一个事件(这里采用的jQuery的写法).f1.on('done', f2);上面这行代码的意思是,当f1发生done事件,就执行f2.然后,对f1进行改写:function f1(){setTimeout(function () {// f1的任务代码f1.trigger('done');}, 1000);}f1.

JavaScript异步编程设计快速响应的网络应用

JavaScript已然成为了多媒体.多任务.多内核网络世界中的一种单线程语言.其利用事件模型处理异步触发任务的行为成就了JavaScript作为开发语言的利器.如何深入理解和掌握JavaScript异步编程变得尤为重要!!!<JavaScript异步编程设计快速响应的网络应用>提供了一些方法和灵感. 一.深入理解JavaScript事件 1. 事件的调度 JavaScript事件处理器在线程空闲之前不会运行(空闲时运行). var start = new Date(); setTimeout

JavaScript异步编程(2)- 先驱者:jsDeferred

原文出处: linkFly   欢迎分享原创到伯乐头条 JavaScript当前有众多实现异步编程的方式,最为耀眼的就是ECMAScript 6规范中的Promise对象,它来自于CommonJS小组的努力:Promise/A+规范. 研究javascript的异步编程,jsDeferred也是有必要探索的:因为Promise/A+规范的制定基本上是奠定在jsDeferred上,它是javascript异步编程中里程碑式的作品.jsDeferred自身的实现也是非常有意思的. 本文将探讨项目js

深入解析Javascript异步编程

这里深入探讨下Javascript的异步编程技术.(P.S. 本文较长,请准备好瓜子可乐 :D) 一. Javascript异步编程简介 至少在语言级别上,Javascript是单线程的,因此异步编程对其尤为重要. 拿nodejs来说,外壳是一层js语言,这是用户操作的层面,在这个层次上它是单线程运行的,也就是说我们不能像Java.Python这类语言在语言级别使用多线程能力.取而代之的是,nodejs编程中大量使用了异步编程技术,这是为了高效使用硬件,同时也可以不造成同步阻塞.不过nodejs

5分种让你了解javascript异步编程的前世今生,从onclick到await/async

javascript与异步编程 为了避免资源管理等复杂性的问题,javascript被设计为单线程的语言,即使有了html5 worker,也不能直接访问dom. javascript 设计之初是为浏览器设计的GUI编程语言,GUI编程的特性之一是保证UI线程一定不能阻塞,否则体验不佳,甚至界面卡死. 一般安卓开发,会有一个界面线程,一个后台线程,保证界面的流畅.由于javascript是单线程,所以采用异步非阻塞的编程模式,javascript的绝大多数api都是异步api. 本文是本人的一个

JavaScript 异步编程

JavaScript 异步编程 第一章 深入理解JavaScript事件 1. javascirpt一般是单线程执行,setTimeout 和 setInterval 仅当cpu空闲时执行. var start = new Date; setTimeout(function(){ var end = new Date; console.log('Time elapsed:', end - start, 'ms'); }, 500); while (new Date - start < 1000)

转: Promises与Javascript异步编程

在如今都追求用户体验的时代,Ajax应用真的是无所不在.加上这些年浏览器技术.HTML5以及CSS3等的发展,越来越多的富Web应用出现:在给与我们良好体验的同时,Web开发人员在背后需要处理越来越多的异步回调逻辑. 笔者对最近读完的<Async Javascript-Build More Responsive Apps with Less Code>(Javascript异步编程-设计快速响应的网络应用)一书以及部分资料,整理了我认为比较重要的一些点以及容易理解错的地方,使大家对 Promi