第十二章:异步处理 第十一章:事件系统

浏览器与后端的nodejs存在这各类消耗巨大或堵塞线程的行为。javascript

对于javascript这样单线程的东西惟一解耦的方法就是提供异步的api。异步的API是怎么的呢,简单来讲,就是不会当即执行的方法html

比方来讲,一个长度为1000的数组,在for循环内,可能不到几毫秒就执行完毕,若在后端的其它语言,则耗时更少。但有的时候,咱们不须要这么快的操做,咱们须要在页面上用肉眼看到执行的每一步,那就须要异步API。还有些操做,好比加载资源,想快也快不了,它不可能一会儿提供给您,须要等待。但也不能一直这么等待下去,咱们得容许咱们跳过这些加载资源的逻辑,执行下面的代码。因而,浏览器先作出两个api,setTimeout,setInterval。后面出现各类事件的回调,它只有用户执行了某种操做才会触发。再以后,就更多了,XHR,postMeeage,webWorkor,setImmediate,requestAnimationFrame等。前端

这些API方法都用一个共同特色,就是拥有一个回调函数,描述一下子干什么,有的异步的API还提供了中断的API。好比clearTime,clearInterval,clearImmediate,cancelAnimationFrame。java

随着iframe的挖掘和XHR的出现,无缝刷新让用户驻留在同一个页面上的事件愈来愈长,不少功能都机制在一个页面,实现这些功能,咱们就须要从后端加载数据与模板,来拼装这些新区域。这些加载数据与模板的请求多是并行的,多是存在依赖的。只有全部的模板与数据存在时,咱们才能顺利拼接出HTML子页面插到正确的位置上。面对这些复杂的流程,前端们不得不发明一些新模式来对应它们。最先被发明出来的是"回调地狱(callback hell)",这应该是一个技能。事实上,几乎javascript中的全部异步函数都用到了回调,连续执行几个异步函数的结果就是层层嵌套的回调函数,以及随之而来的复杂的代码。所以,回调就是程序员的goto语句。node

此外,这样的写法并非一路顺风,若是有一个写错了呢?对于javascript这样单线程的语言,每每是致命的,必须try....catch,但try....catch语句只能捕捉当前抛出的异常,对后来执行的代码无效。程序员

这里不难理解,domReady,动画,Ajax,在骨子里都是同同样东西,倘若能将它们抽象成一个东西,很是有用的web

setTimeout与setInterval后端

首先,咱们的深刻学习一个这两个API。对咱们建立更有用的异步模型很是有用。api

1.若是回调的执行时间大于间隔间隔,那么浏览器会继续执行它们,致使真正的间隔比原来大一点
2.它们存在一个最小的时钟间隔,在IE6-IE8中为15.6ms,后来精准到10ms,IE10为4ms,其它的浏览器相仿。咱们能够试着求其值。数组

    function test(count, ms){
        var C = 1;
        var time = [new Date() * 1];
        var id = setTimeout(function () {
            time.push(new Date() * 1);
            C += 1;
            if (C <= count) {
                setTimeout(arguments.callee, ms);
            } else {
                clearTimeout(id);
                var tl = time.length;
                var av = 0;
                for (var i = 1; i < tl; i++) {
                    var n = time[i] - time[i - 1]; //收集每一次与上一次相差的时间数
                    av += n; 
                }
                console.log(av / count) ;//取得平均值
            }
        },ms)
    }
    window.onload = function() {
        var id = setTimeout (function(){
            test(100, 1);
            clearTimeout(id)
        },3000)
    }

 各个浏览器和系统时间各不相同,咱们或许有办法改造下setTimeout,利用image死链时当即执行onerror回调的状况进行改造。

    var orig_setTimeout = window.setTimeout;
    window.setTimeout = function (fun, wait) {
        if (wait < 15) {
            orig_setTimeout(fun, wait);
        } else {
            var img = new Image();
            img.onload = img.onerror = function(){
                fun()
            };
            img.src = "data:,foo"
        }
    }

有关零秒延迟,此回调会放在一个能当即执行的时段进行触发。javascript大致自上而下执行,但中间穿插着DOM渲染,事件回应等异步代码,它们将组成一个队列,零秒延迟将进行队列操做。

标准浏览器都支持额外参数,从第三个参数起,做为回调传参传入!

    setTimeout(function(){
        alert([].slice.call(arguments))
    },10,1,2,4)

Mochikit Deferred(deferred),JSdeferred,jQuery Deferred,Promise/A mmDeferred等框架涉及到太多跨越式的内容,此处仅作备注。

咱们说下异步处理的前景,在异步处理上,yield能够轻松的以同步的形式写出异步的代码,只要将它们放到某个函数体内。基于这个思路,有几个库被开发出来,例如deferred-generator,taskjs,gens,CO,tamejs,windjs。前四个基于原生的yield,后两个基于源码预编译。

本章内容结束

上一章:第十一章:事件系统  下一章:第十三章: 动画引擎

相关文章
相关标签/搜索