互联网依赖于通讯技术(通讯依赖url),无论使用神马架构,通讯都是必须被考虑到的,任何通讯架构也是通过原生+业务产生的api

img

在控制台中输入

$('<img src="http://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/003/monkey/9.gif">')
$('<img src="http://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/003/monkey/9.gif">')
$('<img src="http://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/003/monkey/9.gif">')

浏览器将会对该地址进行请求一次,这就是最为原始的image通讯,可以看到,image初始化后立即请求通讯只能发送get请求,不接受返回参数(直接立即为图片)-->so,这有什么鬼用..

通讯依赖url,url代表互联网资源,互联网资源有分静态资源和服务,如果将图片的地砖,转换为一个服务的话

网络臭虫

img标签会自动访问src,此时若src为一个服务地址,对应请求如下

app.get('/image', function(req, res) {
    console.log(req.cookies);
    console.log(req.originalMethod);
    console.log(req.baseUrl);
    console.log(req.ip);
    res.json({
        msg: 'ok'
    });
});

此时请求

$('<img src="http://localhost:9000/image">')

就会获取浏览页面内包括访问时间,网址,ip甚至cookie在内的诸多资料,更重要的是,会告诉该服务我已经打开了-->如何确认邮件被人阅读过的终极技巧(返回1个像素图效果更佳),word同理,当然,现在word大都会将图片下载到本地

app.get('/image', function(req, res) {
    console.log("这孙子查看了我的邮件",req.ip);
    res.sendFile(__dirname + '/1.jpeg');
});

预加载

同一个地址只会加载一次,这就是预加载,so...

function loadImages(array) {
    if (array.forEach) {
        array.forEach(function(src) {
            $('<img src="'+src+'">')
        })
    }
}

显然,jquery在这里很没有存在感

function loadImage(array) {
    if (array.forEach) {
        var img=new Image();
        array.forEach(function(src) {
            img.src=src;
        })
    }
}

使用原生方式

function loadImage(array) {
    if (array.forEach) {
        array.forEach(function(src) {
            var img = new Image();
            img.src = src;
        })
    }
}

注:js是单线程,图片是多线程下载,下载触发是在主线程上,在触发前修改src,只会触发最后一次,so-->

只有一个image的错误的姿势:

function loadImage(array) {
    if (array.forEach) {
     var img = new Image();
        array.forEach(function(src) {
            img.src = src;
        })
    }
}

这里只会显示一次,有人认为是修改太快了,请求事件没有触发,只要让src被赋值后,浏览器喘口气就可以发送请求了-->

认为src获取时间太短的错误的姿势:

function loadImage(array) {
    if (array.forEach) {
        var img = new Image();
        array.forEach(function(src) {
            var i = new Date().getTime() + 1000;
            while (i > new Date().getTime())
                img.src = src;
        })
    }
}

与获取src的时间无关,js是单线程,触发事件需要在主线程上,回归到主线成触发就可以了,典型的setTime的正确使用姿势

了解js单线程原理的`正确的姿势`:

function loadImage(array) {
    if (array.forEach) {
        var img = new Image();
        array.forEach(function(src, index) {
            setTimeout(function() {
                img.src = src;
            },0)
        })
    }
}

可以发现前四个依然报错,状态为canceled,查看详情可以看见,没有response

请求既可以服务端中断,也可以客户端中断,客户端的中断可以在发送请求前,也可以在发送请求后,放弃监听,so

到这里,形式已经很明朗了,对付这种多线程只能创建多个Image实例进行响应,如果足够的蛋疼的话,也可以将它改为同步型的

同步加载,菊花链:

function loadImage(array) {
    if (array.forEach) {
        var img = new Image();
        var i = 0;
        img.onload = function() {
                img.src = array[++i]||'';//undefined也会触发请求,蛋疼
        }
        img.src = array[0];
    }
}

增加服务响应时间,可以看见图片一个个加载出来,不过逻辑使用太多,依赖变量i,可以使用pop的方式进一步简化(无视顺序)

function loadImage(array) {
    if (array.forEach) {
        var img = new Image();
        img.onload = function() {
             img.src = array.pop()||'';//undefined也会触发请求,蛋疼
        }
        img.src = array.pop();
    }
}

总之 img是一个单项的服务请求

script

根img一样的src,相对于img的一定会得到图片,script也一定会的到脚本,并根据type(虽然只有一个),选择引擎进行执行,看起来完全没区别,对吧

function loadScript(array) {
    if (array.forEach) {
        array.forEach(function(src) {
            var script = document.createElement("script");
            script.src = src;
            document.getElementsByTagName('HEAD').item(0).appendChild(script);
        })
    }
}

相比于HTMLImageElement,HTMLScriptElement必须至于domcument中才能被加载,image的预加载就是所谓的浏览器支持吧

控制台中,运行以下代码,就可以使用jquery了,也算是一种不用vpn,解决不考虑国情使用googleCDN些例子的方式吧

var script = document.createElement("script");
script.src = 'http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js';
script.onload = function() {
    console.log($().jquery)
}
document.getElementsByTagName('HEAD').item(0).appendChild(script);

 

如果了解浏览器的时间线,就会记得script是同步加载(同步,依赖顺序),而image是异步加载(多线程),但这里的加载绝对是异步的

原因很简单,初始化界面时script的同步是对document.write的依赖,此时document.write还处于打开状态,作为可以进行操作的脚本必须有可理解的顺序,否则界面结果不可测,而初始化结束后,document.write已经关闭,系统对script的加载顺序就无所谓了,如果对script的加载顺序有要求,那使用菊花链的方式进行加载就可以了

function loadJs(src, fn) {
    var script= document.createElement("script");
    script.src = src;
    script.onload = fn;
    document.getElementsByTagName('HEAD').item(0).appendChild(script);
}

//{src:'http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js',srcs:['1.js','2.js','3.js']}
function load(objs){
    loadJs(objs.src,function(){
        objs.srcs.forEach(function(src){
            loadJs(src);
        })
    })
}

load({src:'http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js',srcs:['1.js','2.js','3.js']})

相对于img,script加载完成后会使用特定的引擎进行执行,只要是可以执行的,都是正确的,so...邪恶的jsonp,就这么诞生了,通过编辑正确的语法,进行数据的通讯

//一般而言的回调函数
function cb(data){
    console.log(data);
}

function loadJs(src) {
    var script= document.createElement("script");
    script.src = src;
    document.getElementsByTagName('HEAD').item(0).appendChild(script);
}

后台,直接使用静态文件-->拼写语法

cb({
    a:1,
    b:2
})

只要我在执行

loadJs('1.js')

就会执行cb的回调,非常机智的写法,但也包含了蛋蛋的忧伤...

类似于img,虽然跨域,没有任何条件,但依然只能发送get请求,而且从业务(语意)上看,script当个加载器就好

iframe

 

posted on 2015-11-04 19:42  Glimis  阅读(250)  评论(0编辑  收藏  举报