Underscorejs 'defer' (или setTimeout 1) не работает последовательно
В крупномасштабном приложении JavaScript у меня есть похожий случай:
var $box = $('#box');
var expensiveOperation = function () {
for (var i = 0; i < 10000; i++) {
for (var j = 0; j < 4500; j++) {
Math.random();
}
}
};
$('#show').click(function () {
$box.show();
expensiveOperation();
});
$('#showDefer').click(function () {
$box.show();
_.defer(expensiveOperation);
});
$('#hide').click(function () {
$box.hide();
expensiveOperation();
});
$('#hideDefer').click(function () {
$box.hide();
_.defer(expensiveOperation);
});
#box {
background-color:red;
width:100px;
height:100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box"></div>
<button id="show">show</button>
<button id="showDefer">show defer</button>
<button id="hide">hide</button>
<button id="hideDefer">hide defer</button>
Ссылка на jsFiddle, на всякий случай: http://jsfiddle.net/oymaterz/5/
Я хочу скрыть или показать элемент DOM и выполнить дорогостоящую операцию. Из соображений производительности я хочу всегда обеспечивать, чтобы показ / скрытие выполнялись первыми (то есть в верхней части стека выполнения). Это продемонстрировано в приведенном мною примере (с использованием отложенного подчеркивания) и его работоспособности в последней версии Chrome. Кроме того, приведенный выше пример не работает на IE11. Спрятать / показать отложенное все еще медленно.
Тем не менее, когда я делаю то же самое в моем приложении, оно работает только периодически, и странно, что IE11, кажется, постоянно работает нормально.
Есть идеи, почему я так поступаю?
1 ответ
Я нашел решение своей проблемы. Хотя ожидается, что _.defer (из setTimeout 1) должен был сработать... в моем случае это было не совсем согласованно. В итоге я использовал метод requestAnimationFrame. Вот обновленная версия:
var expensiveOperation = function () {
for (var i = 0; i < 10000; i++) {
for (var j = 0; j < 4500; j++) {
Math.random();
}
}
};
var $box1 = $('#box-1');
$('#show-1').click(function () {
$box1.show();
expensiveOperation();
});
$('#showDefer').click(function () {
$box1.show();
_.defer(expensiveOperation);
});
$('#hide-1').click(function () {
$box1.hide();
expensiveOperation();
});
$('#hideDefer').click(function () {
$box1.hide();
_.defer(expensiveOperation);
});
var $box2 = $('#box-2');
$('#show-2').click(function () {
$box2.show();
expensiveOperation();
});
$('#showRequestAnimationFrame').click(function () {
var flag = true;
requestAnimationFrame(function showAnimFrame(){
if(flag) {
$box2.show();
flag = false;
requestAnimationFrame(showAnimFrame);
} else expensiveOperation();
});
});
$('#hide-2').click(function () {
$box2.hide();
expensiveOperation();
});
$('#hideRequestAnimationFrame').click(function () {
var flag = true;
requestAnimationFrame(function showAnimFrame(){
if(flag) {
$box2.hide();
flag = false;
requestAnimationFrame(showAnimFrame);
} else expensiveOperation();
});
});
#box-1 {
background-color:red;
width:100px;
height:100px;
}
#box-2 {
background-color:blue;
width:100px;
height:100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box-1"></div>
<button id="show-1">show</button>
<button id="showDefer">show defer</button>
<button id="hide-1">hide</button>
<button id="hideDefer">hide defer</button>
<p></p>
<div id="box-2"></div>
<button id="show-2">show</button>
<button id="showRequestAnimationFrame">show requestAnimationFrame</button>
<button id="hide-2">hide</button>
<button id="hideRequestAnimationFrame">hide requestAnimationFrame</button>
Ссылка на jsFiddle, на всякий случай: http://jsfiddle.net/oymaterz/6/
Стоит отметить, что requestAnimationFrame не поддерживается в IE8. Если вам нужна поддержка, я предлагаю использовать превосходный GIST Пола Айриша для кросс-браузерной совместимости.
Я надеюсь, что это поможет кому-то в такой же ситуации, как и я. Теперь он отлично работает для меня и доказал, что спасает жизнь.