互联网依赖于通讯技术(通讯依赖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