zoukankan      html  css  js  c++  java
  • 第十二章:异步处理

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

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

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

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

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

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

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

    setTimeout与setInterval

    首先,我们的深入学习一个这两个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,后两个基于源码预编译。

    本章内容结束

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

  • 相关阅读:
    Maximum Flow Exhaustion of Paths Algorithm
    ubuntu下安装java环境
    visualbox使用(二)
    vxworks一个超级奇怪的错误(parse error before `char')
    February 4th, 2018 Week 6th Sunday
    February 3rd, 2018 Week 5th Saturday
    February 2nd, 2018 Week 5th Friday
    February 1st, 2018 Week 5th Thursday
    January 31st, 2018 Week 05th Wednesday
    January 30th, 2018 Week 05th Tuesday
  • 原文地址:https://www.cnblogs.com/ahthw/p/4741123.html
Copyright © 2011-2022 走看看