淡出超时的多个元素只会淡出列表中的最后一个元素
Fadeout multiple elements with timeout only fades last one in list
我正在尝试在几秒钟后淡出消息容器。通常只有一个,并且可以正常工作,但是当有 2 个或更多时,似乎只有最后一个得到处理。
代码:
function fadeOut(elementToFade) {
var element = document.getElementById(elementToFade);
console.log(`fo element = ${element}, ${element.id}`)
element.style.opacity = (parseFloat(element.style.opacity) - 0.1).toString();
if (parseFloat(element.style.opacity) <= 0.0) {
element.style.display = "none";
} else {
setTimeout("fadeOut(\"" + elementToFade + "\")", 150);
// setTimeout("fadeOut(\"" + element.id + "\")", 150);
}
};
var message_elements_nodelist = document.querySelectorAll("div[id^='message_container']");
var pauseBeforeFadeout = 5000;
for (var i = 0; i < message_elements_nodelist.length; i++) {
var el = document.getElementById(message_elements_nodelist[i].id)
console.log(`element = ${el}, ${el.id}`)
setTimeout(function () {
el.style.opacity = "1.0";
fadeOut(el.id);
}, pauseBeforeFadeout);
};
控制台日志显示:
element = [object HTMLDivElement], message_container-0
element = [object HTMLDivElement], message_container-1
2fo element = [object HTMLDivElement], message_container-1
10fo element = [object HTMLDivElement], message_container-1
所以代码找到了两个元素,但是超时似乎只应用于列表中的最后一个元素,我无法理解为什么会这样。
编辑
放入 Promise
现在看起来像这样:
const message_elements_nodelist = document.querySelectorAll("div[id^='message_container']")
const pauseBeforeFadeout = 5000
async function fadeOut(elementToFade) {
const element = document.getElementById(elementToFade);
console.log(`fo element = ${element}, ${element.id}`)
element.style.opacity = (parseFloat(element.style.opacity) - 0.1).toString()
if (parseFloat(element.style.opacity) <= 0.0) {
element.style.display = "none"
} else {
setTimeout("fadeOut(\"" + elementToFade + "\")", 150)
}
}
async function fadeOutAllMessages() {
for (let i = 0; i < message_elements_nodelist.length; i++) {
const el = document.getElementById(message_elements_nodelist[i].id)
console.log(`element = ${el}, ${el.id}`)
await new Promise(resolve => setTimeout(() => {
el.style.opacity = "1.0"
fadeOut(el.id)
}, pauseBeforeFadeout))
}
}
fadeOutAllMessages()
不幸的是,现在第一条消息已被清除,但第二条消息未被清除,console.log
条消息如下所示:
element = [object HTMLDivElement], message_container-0
fo element = [object HTMLDivElement], message_container-0
9 fo element = [object HTMLDivElement], message_container-0
最后 9 条消息在第一条消息出现 5 秒后出现,所以一个 await
正在工作,然后它似乎只用第一个循环实例将它们全部捆绑在一起。
发生这种情况是因为在 for 循环中使用了异步方法(在本例中为 setTimeout)。在异步方法执行之前,变量 i
已经递增(循环不等待内部的异步代码),因此 setTimeout 将被执行多次并且变量 i
总是在它的最后一个值回调。
考虑在循环中使用 async/await
。
async function yourFunction() {
for (let i = 0; i < 10; i++) {
// wait for the promise before incrementing i and advancing the loop
await new Promise(resolve => resolve(setTimeout(() => console.log(i),
1000)))
}
}
另一个解决方案是调用在循环外创建的函数。
const setDelay = (i) => {
setTimeout(() => {
console.log(i);
}, 1000);
}
for (let i = 0; i < 5; i++) {
setDelay(i);
}
您可以在本主题中找到更多示例:
Asynchronous Process inside a javascript for loop
我正在尝试在几秒钟后淡出消息容器。通常只有一个,并且可以正常工作,但是当有 2 个或更多时,似乎只有最后一个得到处理。
代码:
function fadeOut(elementToFade) {
var element = document.getElementById(elementToFade);
console.log(`fo element = ${element}, ${element.id}`)
element.style.opacity = (parseFloat(element.style.opacity) - 0.1).toString();
if (parseFloat(element.style.opacity) <= 0.0) {
element.style.display = "none";
} else {
setTimeout("fadeOut(\"" + elementToFade + "\")", 150);
// setTimeout("fadeOut(\"" + element.id + "\")", 150);
}
};
var message_elements_nodelist = document.querySelectorAll("div[id^='message_container']");
var pauseBeforeFadeout = 5000;
for (var i = 0; i < message_elements_nodelist.length; i++) {
var el = document.getElementById(message_elements_nodelist[i].id)
console.log(`element = ${el}, ${el.id}`)
setTimeout(function () {
el.style.opacity = "1.0";
fadeOut(el.id);
}, pauseBeforeFadeout);
};
控制台日志显示:
element = [object HTMLDivElement], message_container-0
element = [object HTMLDivElement], message_container-1
2fo element = [object HTMLDivElement], message_container-1
10fo element = [object HTMLDivElement], message_container-1
所以代码找到了两个元素,但是超时似乎只应用于列表中的最后一个元素,我无法理解为什么会这样。
编辑
放入 Promise
现在看起来像这样:
const message_elements_nodelist = document.querySelectorAll("div[id^='message_container']")
const pauseBeforeFadeout = 5000
async function fadeOut(elementToFade) {
const element = document.getElementById(elementToFade);
console.log(`fo element = ${element}, ${element.id}`)
element.style.opacity = (parseFloat(element.style.opacity) - 0.1).toString()
if (parseFloat(element.style.opacity) <= 0.0) {
element.style.display = "none"
} else {
setTimeout("fadeOut(\"" + elementToFade + "\")", 150)
}
}
async function fadeOutAllMessages() {
for (let i = 0; i < message_elements_nodelist.length; i++) {
const el = document.getElementById(message_elements_nodelist[i].id)
console.log(`element = ${el}, ${el.id}`)
await new Promise(resolve => setTimeout(() => {
el.style.opacity = "1.0"
fadeOut(el.id)
}, pauseBeforeFadeout))
}
}
fadeOutAllMessages()
不幸的是,现在第一条消息已被清除,但第二条消息未被清除,console.log
条消息如下所示:
element = [object HTMLDivElement], message_container-0
fo element = [object HTMLDivElement], message_container-0
9 fo element = [object HTMLDivElement], message_container-0
最后 9 条消息在第一条消息出现 5 秒后出现,所以一个 await
正在工作,然后它似乎只用第一个循环实例将它们全部捆绑在一起。
发生这种情况是因为在 for 循环中使用了异步方法(在本例中为 setTimeout)。在异步方法执行之前,变量 i
已经递增(循环不等待内部的异步代码),因此 setTimeout 将被执行多次并且变量 i
总是在它的最后一个值回调。
考虑在循环中使用 async/await
。
async function yourFunction() {
for (let i = 0; i < 10; i++) {
// wait for the promise before incrementing i and advancing the loop
await new Promise(resolve => resolve(setTimeout(() => console.log(i),
1000)))
}
}
另一个解决方案是调用在循环外创建的函数。
const setDelay = (i) => {
setTimeout(() => {
console.log(i);
}, 1000);
}
for (let i = 0; i < 5; i++) {
setDelay(i);
}
您可以在本主题中找到更多示例: Asynchronous Process inside a javascript for loop