我最近下载了一个不错的mootools插件,为我的网站上的搜索结果提供评分系统:MooStarRating。
它工作得很好,但初始化起来很慢。以下是我记录的执行时间(用于撤回50个搜索结果)。
======== starrating ========
init: 0.06ms 50
img: 5.40ms 50
str: 0.54ms 50
each: 3.04ms 50
inject: 0.86ms 50
end: 1.52ms 50
subtotal: 11.42ms 50
-----------------
total: 571.00ms
以下是这些日志引用的initialize
函数(仅供参考):
initialize: function (options) {
lstart("starrating");
// Setup options
this.setOptions(options);
// Fix image folder
if ((this.options.imageFolder.length != 0) && (this.options.imageFolder.substr(-1) != "/"))
this.options.imageFolder += "/";
// Hover image as full if none specified
if (this.options.imageHover == null) this.options.imageHover = this.options.imageFull;
lrec("init");
// Preload images
try {
Asset.images([
this.options.imageEmpty,
this.options.imageFull,
this.options.imageHover
]);
} catch (e) { };
lrec("img");
// Build radio selector
var formQuery = this.options.form;
this.options.form = $(formQuery);
if (!this.options.form) this.options.form = $$('form[name=' + formQuery + "]")[0];
if (this.options.form) {
var uniqueId = 'star_' + String.uniqueID();
this.options.form.addClass(uniqueId);
this.options.selector += 'form.' + uniqueId + ' ';
}
this.options.selector += 'input[type=radio][name=' + this.options.radios + "]";
// Loop elements
var i = 0;
var me = this;
var lastElement = null;
var count = $$(this.options.selector).length;
var width = this.options.width.toInt();
var widthOdd = width;
var height = this.options.height.toInt();
if (this.options.half) {
width = (width / 2).toInt();
widthOdd = widthOdd - width;
}
lrec("str");
$$(this.options.selector).each(function (item) {
// Add item to radio list
this.radios[i] = item;
if (item.get('checked')) this.currentIndex = i;
// If disabled, whole star rating control is disabled
if (item.get('disabled')) this.options.disabled = true;
// Hide and replace
item.setStyle('display', 'none');
this.stars[i] = new Element('a').addClass(this.options.linksClass);
this.stars[i].store('ratingIndex', i);
this.stars[i].setStyles({
'background-image': 'url("' + this.options.imageEmpty + '")',
'background-repeat': 'no-repeat',
'display': 'inline-block',
'width': ((this.options.half && (i % 2)) ? widthOdd : width),
'height': height
});
if (this.options.half)
this.stars[i].setStyle('background-position', ((i % 2) ? '-' + width + 'px 0' : '0 0'));
this.stars[i].addEvents({
'mouseenter': function () { me.starEnter(this.retrieve('ratingIndex')); },
'mouseleave': function () { me.starLeave(); }
});
// Tip
if (this.options.tip) {
var title = this.options.tip;
title = title.replace('[VALUE]', item.get('value'));
title = title.replace('[COUNT]', count);
if (this.options.tipTarget) this.stars[i].store('ratingTip', title);
else this.stars[i].setProperty('title', title);
}
// Click event
var that = this;
this.stars[i].addEvent('click', function () {
if (!that.options.disabled) {
me.setCurrentIndex(this.retrieve('ratingIndex'));
me.fireEvent('click', me.getValue());
}
});
// Go on
lastElement = item;
i++;
}, this);
lrec("each");
// Inject items
$$(this.stars).each(function (star, index) {
star.inject(lastElement, 'after');
lastElement = star;
}, this);
lrec("inject");
// Enable / disable
if (this.options.disabled) this.disable(); else this.enable();
// Fill stars
this.fillStars();
lrec("end");
return this;
},
因此,函数中最慢的部分是:
// Preload images
try {
Asset.images([
this.options.imageEmpty,
this.options.imageFull,
this.options.imageHover
]);
} catch (e) { };
这很奇怪。 Asset.images
做了什么?在浏览器加载这些图像之前,脚本是否会阻塞?有没有办法预加载运行得更快的图像?
如何让我页面上的脚本执行得更快?对于他们来说,执行800毫秒是个大问题,但200毫秒仍然很糟糕。目前,我的搜索结果一下子就存在了。是否可以单独创建单个搜索结果,以便在创建时不阻止浏览器?同样,是否可以针对搜索结果的各个组件执行此操作,例如MooStarRating插件?
答案 0 :(得分:1)
没有。 Asset.images是非阻塞的,因为它们中的每一个都是单独加载的,并且在完成所有操作时都会调度一个单一事件。
加载的速度取决于浏览器,但它将具有多线程功能,无论从同一主机并行下载的能力如何。
https://github.com/mootools/mootools-more/blob/master/Source/Utilities/Assets.js#L115-129
立即返回一个Element集合,其中包含可能仍在下载的PROMISE元素。没关系 - 你可以用它来注入els,附加事件,类等等 - 你只是无法读取像宽度,高度这样的图像属性。
每个单独的图片都有自己的onload
,它会触发onProgress
,当完成所有操作时,我会建议你启用它,删除try / catch阻止并查看哪个图像正在创建延迟。你肯定不需要等待Asset.images的任何东西回来。
你似乎也将它用作'主要缓存'方法,而不是任何东西 - 因为你并没有真正将引用保存到类实例中。您的“每个”迭代可能会被优化,因此如果对象和函数被缓存,它会占用一半的时间,因此引用也是如此。如果你可以使用事件委托可能更多。
由于javascript的单线程性质,为了回答有关不冻结浏览器的问题,您可以通过setTimeout(或mootools中的Function.delay)将代码设置为0或10ms(由于浏览器解释)而延迟代码。你也可以编写函数来完成一个回调,你可以在其中传递函数结果(如果有的话)(想想ajax!)。