预加载,然后执行

I talked before about using an object element to load scripts and styles without executing/applying them to the current document. And this is nice for preloading assets - faster and less error-prone than simple inclusion if the document or iframe.

之前讨论使用object元素来加载脚本和样式,而无需执行/将其应用于当前文档。 这对于预加载资产非常有用-比简单包含文档或iframe更快,更少出错。

But what about preloading assets (scripts) and then executing them on the current page? Turns out it works just fine, like so:

但是,如何预加载资产(脚本)然后在当前页面上执行它们呢? 事实证明,它工作正常,就像这样:

  • create an object element and point its data to the JavaScript file to be loaded

    创建一个object元素并将其data指向要加载JavaScript文件

  • listen to the load event of the object

    监听objectload事件

  • once loaded, create a script element and point its src to the file, which would be already cached

    加载后,创建一个script元素并将其src指向该文件,该文件将已经被缓存

  • optionaly, execute a callback function once the script element is properly inserted into the DOM

    可选地,将script元素正确插入DOM后,执行回调函数

Something like this:

像这样:

function yield(file, callback) {
    var o = document.createElement('object');
    o.data = file;
        
    o.width  = 0;
    o.height = 0;
    
    o.onload = function() {
        var s = document.createElement('script');
        s.src = file;
        s.onload = function() {
            callback(o, file);
        };
        document.getElementsByTagName('head')[0].appendChild(s);
        
    };
    
    document.body.appendChild(o);
}

但是,但是..为什么呢? (But, but.. why?)

Well, first off it's yet another way to load JavaScript files asynchronously, in a non-blocking fashion. And that's a good thing. Async = win. This method sure beats others such as document.write (eek) or iframe. It has advantage over XHR because there's no same-domain restriction. DOM include is probably the only simpler and more robust method, but there are cases where the object element might be preferable.

好吧,首先,它是另一种以非阻塞方式异步加载JavaScript文件的方法。 那是一件好事。 异步=胜利。 这种方法肯定胜过其他文件,例如document.write(eek)或iframe。 与XHR相比,它具有优势,因为没有相同域的限制。 DOM include可能是唯一更简单,更可靠的方法,但是在某些情况下,object元素可能更可取。

DOM-included scripts in FF and Opera always execute in order. That's cool, but sometimes you may prefer out of order async execution. Whenever a script is ready - go! Or sometimes you may prefer if the script is not executed at all! That may sound odd (why would I load it if I don't want to execute it?) but I have a use case - auto-complete. When your data source is on another domain and you can't use XHR, then JSON-P would be the way to go. But the network is a jungle and anything can happen.

FF和Opera中包含DOM的脚本始终按顺序执行。 这很酷,但是有时您可能更喜欢乱序的异步执行。 只要脚本准备就绪,就可以开始! 或者有时您可能更喜欢脚本根本不执行! 这听起来可能很奇怪(如果我不想执行它,为什么要加载它?),但是我有一个用例-自动完成。 当您的数据源位于另一个域上并且您不能使用XHR时,则可以使用JSON-P。 但是网络是一片丛林,任何事情都可能发生。

Say you make requests for auto-complete suggestions with queries "h", "he", "hel", "hell", "hello". For some reason "hel" is really slow and you already have the results for "hell" and even "hello". What you want to do is just kill and cancel the "hel" response, who cares - it's outdated already. But if you use JSONP in FF and Opera "hel" will block the others. If order is not preserved it might be even weirder - you update the page with the "hello" suggestion and then "hel" finally arrives and updates the suggestion once again. Fail.

假设您使用查询“ h”,“ he”,“ hel”,“ hell”,“ hello”来请求自动完成建议。 出于某种原因,“ hel”确实很慢,并且您已经获得了“ hell”甚至“ hello”的结果。 您想要做的就是杀死并取消关心的“ hel”响应-它已经过时了。 但是,如果在FF中使用JSONP,Opera的“ hel”将阻止其他人。 如果未保留订单,则可能会更奇怪-您使用“ hello”建议更新页面,然后“ hel”最终到达并再次更新建议。 失败。

Using the object element approach you can keep a list of requests that went out and simply choose to ignore previous requests if newer responses are already there.

使用object元素方法,您可以保留已发出请求的列表,如果已经有较新的响应,则只需选择忽略先前的请求即可。

I have a test case even.

我什至有一个测试用例

小字 (Small print)

This technique assumes that the scripts you load don't have any headers preventing caching, otherwise they'll be requested twice.

该技术假定您加载的脚本没有任何阻止缓存的标头,否则它们将被请求两次。

My example code above ignored IE completely, but you can easily make it work, either using new Image() instead of object or tweaking the object with height and width of 1 as shown in the old article. Or you can use the trick that LABjs uses (I think) which is to DOM-insert a script element with invalid type such as cache/javascript. Also you need to listen to onreadystatechange instead of load event when inserting a DOM element.

我上面的示例代码完全忽略了IE,但是您可以轻松地使其工作,或者使用new Image()代替object或者调整高度和宽度为1的对象,如旧文章中所示。 或者,您可以使用LABjs使用的技巧(我认为),该技巧是DOM插入具有无效类型的脚本元素,例如cache/javascript 。 另外,插入DOM元素时,您还需要监听onreadystatechange而不是load事件。

Tell your friends about this post on Facebook and Twitter

FacebookTwitter上告诉您的朋友有关此帖子的信息

翻译自: https://www.phpied.com/preload-then-execute/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值