为什么这个 Javascript setTimeout 和 setInterval 运行 进入竞争状态?
Why is this Javascript setTimeout and setInterval running into a race condition?
document.addEventListener("DOMContentLoaded", function(event) {
window.setInterval(rotateCarousel, 5000);
});
function fadeCarousel(n, e, t, s){
var carousel = window.setInterval(function(){
console.log(t/s);
if (e.children[n].style.opacity>0){
e.children[n].style.opacity = String(parseFloat(e.children[n].style.opacity) - .01);
}
if (e.children[(n+1) % e.childElementCount].style.opacity <1){
e.children[(n+1) % e.childElementCount].style.opacity = String(parseFloat(e.children[(n+1) % e.childElementCount].style.opacity) + .01);
}
}, t/s);
window.setTimeout(function(){
clearInterval(carousel);
},t);
};
function rotateCarousel(){
var carouselinner = document.getElementsByClassName("carousel-inner")[0];
var activeChild = 0;
for (i=0; i< carouselinner.childElementCount; i++){
if (carouselinner.children[i].classList.contains("active")){
activeChild=i;
i=carouselinner.childElementCount;
}
}
fadeCarousel(activeChild, carouselinner, 500, 100);
carouselinner.children[activeChild].classList.remove("active");
carouselinner.children[(activeChild+1) % carouselinner.childElementCount].classList.add("active");
};
.carousel {
z-index: -100;
} /* keeps this behind all content */
.carousel .item {
top:0;
left:0;
position: fixed;
width: 100%;
height: 100%;
background-position: center;
}
.carousel .one {
background-color:green;
background-size: cover;
}
.carousel .two {
background-color:blue;
background-size: cover;
}
.carousel .three {
background-color:yellow;
background-size: cover;
}
.carousel .four {
background-color: red;
background-size: cover;
}
<div id="BackgroundCarousel" class="carousel container slide">
<div class="carousel-inner">
<div class="item one active" style="opacity: 1;"></div>
<div class="item two" style="opacity: 0;"></div>
<div class="item three" style="opacity: 0;"></div>
<div class="item four" style="opacity: 0;"></div>
</div>
</div>
以上是我 运行 喜欢的例子。
我想要做的是让背景的透明度在设定的时间间隔内旋转进出,所以我使用 setInterval
调用函数 rotateCarousel
标记 div
作为显示的 div 并调用转换。
在改变的时候,我想有一个淡入淡出的过渡,所以我有一个函数fadeCarousel
可以在很短的时间内调整两个相邻背景div的不透明度。由于我希望 div 停止褪色,因此我清除了 setTimeout
中的褪色 setInterval
,并延迟了 setInterval
中的所有内容。
似乎当我使用精确值作为清除时间间隔的延迟时,浏览器没有足够的时间来完成 setInterval
淡入淡出,当 setTimeout
运行 clearInterval
,有时淡入淡出的 setInterval
不完整。这让我的背景看起来陷入了转型。
我试图通过提供大约 5 倍的延迟来解决这个问题,这是调用 clearInterval
所需要的,但它有时似乎仍然存在问题(没有很大的余量,似乎每次都有竞争条件)。我也有 console.log
打印出来 t/s
因为在 Firefox 中似乎没有这个 t
& s
会得到优化并且奇怪的事情发生了。
我对 setInterval
和 setTimeout
不了解 - 为什么这里存在竞争条件?
因为当您更改活动元素时您的 for 循环是错误的,您的间隔未完成。这就是为什么当下一个元素处于活动状态时你的间隔已经清除。和你的比赛条件。我已经修复了这段代码,我尝试在清除前向元素间隔后调用设置间隔下一个元素。查看代码片段
var activeChild = -1;
document.addEventListener("DOMContentLoaded", function(event) {
rotateCarousel();
});
function fadeCarousel(n, e, t, s){
var carousel = window.setInterval(function(){
console.log(t/s);
if (e.children[n].style.opacity>0){
e.children[n].style.opacity = String(parseFloat(e.children[n].style.opacity) - .01);
}
if (e.children[(n+1) % e.childElementCount].style.opacity <1){
e.children[(n+1) % e.childElementCount].style.opacity = String(parseFloat(e.children[(n+1) % e.childElementCount].style.opacity) + .01);
}
}, t/s);
window.setTimeout(function(){
console.log("clear");
clearInterval(carousel);
rotateCarousel();
},t);
};
function rotateCarousel(){
activeChild+=1;
var carouselinner = document.getElementsByClassName("carousel-inner")[0];
if(carouselinner.childElementCount <= activeChild){
activeChild = 0;
}
console.log("element: " + activeChild);
if(activeChild > 0){
carouselinner.children[activeChild - 1].classList.remove("active");
}
carouselinner.children[activeChild].classList.add("active");
fadeCarousel(activeChild, carouselinner, 3000, 1000);
};
.carousel {
z-index: -100;
} /* keeps this behind all content */
.carousel .item {
top:0;
left:0;
position: fixed;
width: 100%;
height: 100%;
background-position: center;
}
.carousel .one {
background-color:green;
background-size: cover;
}
.carousel .two {
background-color:blue;
background-size: cover;
}
.carousel .three {
background-color:yellow;
background-size: cover;
}
.carousel .four {
background-color: red;
background-size: cover;
}
<div id="BackgroundCarousel" class="carousel container slide">
<div class="carousel-inner">
<div class="item one" style="opacity: 1;"></div>
<div class="item two active" style="opacity: 0;"></div>
<div class="item three" style="opacity: 0;"></div>
<div class="item four" style="opacity: 0;"></div>
</div>
</div>
您的代码设置调用 rotateCarousel() 的时间间隔,当您的函数 fadeCarousel 被调用时,rotateCarousel 的时间间隔 调用 :) 这使得 fadeCarousel 调用比 interval insite fadeCarousel 函数调用更快。例如:
1: window.setInterval(rotateCarousel, 5000);// A 表示 5s 后 rotateCarousel 将调用。
2: fadeCarousel(activeChild, carouselinner, 500, 100); //B 500 毫秒后关闭。
but: when A make next call 表示在5s之后B已经在4.5s之前完成了。思考:在 A 调用 B 完成后 5000 - (n * 500ms) 那为什么 activeChild 比赛条件(我正在努力提高我的英语)如果你不明白请告诉我举个例子。
document.addEventListener("DOMContentLoaded", function(event) {
window.setInterval(rotateCarousel, 5000);
});
function fadeCarousel(n, e, t, s){
var carousel = window.setInterval(function(){
console.log(t/s);
if (e.children[n].style.opacity>0){
e.children[n].style.opacity = String(parseFloat(e.children[n].style.opacity) - .01);
}
if (e.children[(n+1) % e.childElementCount].style.opacity <1){
e.children[(n+1) % e.childElementCount].style.opacity = String(parseFloat(e.children[(n+1) % e.childElementCount].style.opacity) + .01);
}
}, t/s);
window.setTimeout(function(){
clearInterval(carousel);
},t);
};
function rotateCarousel(){
var carouselinner = document.getElementsByClassName("carousel-inner")[0];
var activeChild = 0;
for (i=0; i< carouselinner.childElementCount; i++){
if (carouselinner.children[i].classList.contains("active")){
activeChild=i;
i=carouselinner.childElementCount;
}
}
fadeCarousel(activeChild, carouselinner, 500, 100);
carouselinner.children[activeChild].classList.remove("active");
carouselinner.children[(activeChild+1) % carouselinner.childElementCount].classList.add("active");
};
.carousel {
z-index: -100;
} /* keeps this behind all content */
.carousel .item {
top:0;
left:0;
position: fixed;
width: 100%;
height: 100%;
background-position: center;
}
.carousel .one {
background-color:green;
background-size: cover;
}
.carousel .two {
background-color:blue;
background-size: cover;
}
.carousel .three {
background-color:yellow;
background-size: cover;
}
.carousel .four {
background-color: red;
background-size: cover;
}
<div id="BackgroundCarousel" class="carousel container slide">
<div class="carousel-inner">
<div class="item one active" style="opacity: 1;"></div>
<div class="item two" style="opacity: 0;"></div>
<div class="item three" style="opacity: 0;"></div>
<div class="item four" style="opacity: 0;"></div>
</div>
</div>
以上是我 运行 喜欢的例子。
我想要做的是让背景的透明度在设定的时间间隔内旋转进出,所以我使用 setInterval
调用函数 rotateCarousel
标记 div
作为显示的 div 并调用转换。
在改变的时候,我想有一个淡入淡出的过渡,所以我有一个函数fadeCarousel
可以在很短的时间内调整两个相邻背景div的不透明度。由于我希望 div 停止褪色,因此我清除了 setTimeout
中的褪色 setInterval
,并延迟了 setInterval
中的所有内容。
似乎当我使用精确值作为清除时间间隔的延迟时,浏览器没有足够的时间来完成 setInterval
淡入淡出,当 setTimeout
运行 clearInterval
,有时淡入淡出的 setInterval
不完整。这让我的背景看起来陷入了转型。
我试图通过提供大约 5 倍的延迟来解决这个问题,这是调用 clearInterval
所需要的,但它有时似乎仍然存在问题(没有很大的余量,似乎每次都有竞争条件)。我也有 console.log
打印出来 t/s
因为在 Firefox 中似乎没有这个 t
& s
会得到优化并且奇怪的事情发生了。
我对 setInterval
和 setTimeout
不了解 - 为什么这里存在竞争条件?
因为当您更改活动元素时您的 for 循环是错误的,您的间隔未完成。这就是为什么当下一个元素处于活动状态时你的间隔已经清除。和你的比赛条件。我已经修复了这段代码,我尝试在清除前向元素间隔后调用设置间隔下一个元素。查看代码片段
var activeChild = -1;
document.addEventListener("DOMContentLoaded", function(event) {
rotateCarousel();
});
function fadeCarousel(n, e, t, s){
var carousel = window.setInterval(function(){
console.log(t/s);
if (e.children[n].style.opacity>0){
e.children[n].style.opacity = String(parseFloat(e.children[n].style.opacity) - .01);
}
if (e.children[(n+1) % e.childElementCount].style.opacity <1){
e.children[(n+1) % e.childElementCount].style.opacity = String(parseFloat(e.children[(n+1) % e.childElementCount].style.opacity) + .01);
}
}, t/s);
window.setTimeout(function(){
console.log("clear");
clearInterval(carousel);
rotateCarousel();
},t);
};
function rotateCarousel(){
activeChild+=1;
var carouselinner = document.getElementsByClassName("carousel-inner")[0];
if(carouselinner.childElementCount <= activeChild){
activeChild = 0;
}
console.log("element: " + activeChild);
if(activeChild > 0){
carouselinner.children[activeChild - 1].classList.remove("active");
}
carouselinner.children[activeChild].classList.add("active");
fadeCarousel(activeChild, carouselinner, 3000, 1000);
};
.carousel {
z-index: -100;
} /* keeps this behind all content */
.carousel .item {
top:0;
left:0;
position: fixed;
width: 100%;
height: 100%;
background-position: center;
}
.carousel .one {
background-color:green;
background-size: cover;
}
.carousel .two {
background-color:blue;
background-size: cover;
}
.carousel .three {
background-color:yellow;
background-size: cover;
}
.carousel .four {
background-color: red;
background-size: cover;
}
<div id="BackgroundCarousel" class="carousel container slide">
<div class="carousel-inner">
<div class="item one" style="opacity: 1;"></div>
<div class="item two active" style="opacity: 0;"></div>
<div class="item three" style="opacity: 0;"></div>
<div class="item four" style="opacity: 0;"></div>
</div>
</div>
您的代码设置调用 rotateCarousel() 的时间间隔,当您的函数 fadeCarousel 被调用时,rotateCarousel 的时间间隔 调用 :) 这使得 fadeCarousel 调用比 interval insite fadeCarousel 函数调用更快。例如:
1: window.setInterval(rotateCarousel, 5000);// A 表示 5s 后 rotateCarousel 将调用。
2: fadeCarousel(activeChild, carouselinner, 500, 100); //B 500 毫秒后关闭。
but: when A make next call 表示在5s之后B已经在4.5s之前完成了。思考:在 A 调用 B 完成后 5000 - (n * 500ms) 那为什么 activeChild 比赛条件(我正在努力提高我的英语)如果你不明白请告诉我举个例子。