• Deffered.js的实现原理


    在艾伦的推荐下,看了一个日本人写的延时加载库,非常轻量,写的很棒。作为我的源码学习的第一编。

    在认真看了两天之后,才看懂它的实现原理,我下面把通自己的理解,进行了精简。只程现原理,方便日后的回顾。<!DOCTYPE HTML>

    <html>
    <head>
    <meta charset="utf-8">
    <title>deffred</title>
    <meta name="Keywords" content="">
    <meta name="Description" content="">
    
    </head>
    <body>
    
    <script type="text/javascript" src="deffered.js"></script>
    
    <script type="text/javascript">
    Deferred.next(function(){
        alert(1)
    //这里直接return ;则会立即调用alert(2),没有异步过程
    return Deferred.wait(3) }).next(function(){ alert(2) }) </script> </body> </html>

    deffered.js是我精简之后的代码,并加了一些注释:

    /**
     * @fileOverview JSDeferred
     * @author       cho45@lowreal.net
     * @version      0.4.0
     * @license
     * JSDeferred Copyright (c) 2007 cho45 ( www.lowreal.net )
     *
     *  针对deferred的原理进行精简
     */ ; // no warnings for uglify
    
    function Deferred () {
        return this.init();
    }
    //定义静态方法
    Deferred.ok = function(x) {return x} //缺省的成功回调
    Deferred.ng = function(x) {throw x}
    //判断是否为Deferred的实例
    Deferred.isDeferred = function (obj) {
        return !!(obj && obj._id === Deferred.prototype._id);
    };
    
    //这个next是挂在Deferred上的静态方法。与实列方法.next是不同的
    Deferred.next = function(fn){
        var d = new Deferred();
        var img = new Image();
        var handler = function(){
            d.canceller();
            d.calls();
        }
        //这个地方个人认为比较巧秒,它利用了img加载成功或错误回调具有异步的特性。
        //保证完整收集这些.next().next()...
        //事实上官方还用了其它两种方式,确保兼容,如setTimeout....
        img.addEventListener('error',handler,false);
        d.canceller = function(){
            img.removeEventListener('error',handler,false);
        }
        //这里用来触发一个img的加载事件
        img.src = "data:image/png," + Math.random();
        if(fn) d.callback.ok = fn;
        return d;
    }
    
    //这里是用来模拟一个比较耗时的异步过程
    //实践中,可能是取数据的过程,如等待ajax回调
    Deferred.wait = function (n) {
        var d = new Deferred(), t = new Date();
        var id = setTimeout(function () {
            d.calls((new Date()).getTime() - t.getTime());
        }, n * 1000);
        d.canceller = function () { clearTimeout(id) };
        return d;
    };
    
    
    Deferred.prototype = {
        _id : 8888, //随便填写,用来判断是否为Deferred的实例
        init : function(){
            this._next = null;
            //使Deferred.isDeferred 判断为假
            this.callback = {
                ok : Deferred.ok,
                ng : Deferred.ng
            }
            return this;
        },
        next  : function (fun) { return this._post("ok", fun) },
    
        calls  : function (val) { return this._fire("ok", val) },
    
        _post : function (okng, fun) {
            //个人认为,理解这里是关键,
            //._next保存一下实例对象,形成一个链
            this._next =  new Deferred();
            this._next.callback[okng] = fun;
            return this._next;
        },
    
        _fire : function (okng, value) {
            var next = "ok";
    
            value = this.callback[okng](value);
            //这里的value如果不是Deferred的实例
            if (Deferred.isDeferred(value)) {
                //加载下一个任务
                value._next = this._next;
            } else {
                //说明没有下一个任务了
                if (this._next) this._next._fire(next, value);
            }
            return this;
        }
    }

    我的重点在于方便理解原理,关于源代码的分析,参看司图正美的博文。此处不在复述。

  • 相关阅读:
    python打包exe pyinstaller 简单使用
    加群请回答两个问题,谢谢合作!
    8080_32位汇编-通用寄存器
    学习8086汇编的准备
    HelloWorld生命周期
    我为什么要学习《深入理解计算机系统》这本书?
    MySQL_1.0
    C++命名空间的玩法
    Linux的 7个运行级别
    Linux基础命令2.0
  • 原文地址:https://www.cnblogs.com/afrog/p/3826150.html
Copyright © 2020-2023  润新知