具有不同时间的for循环中的setTimeout
setTimeout in a for loop with varying time
我有一个不同对象的数组,每个对象包含不同值的时间属性。
我想循环这个数组,里面有一个setTimeout函数,时间就是每个对象的时间属性。
所以我想要的结果是
- 10秒后,打印第一个对象的名称
- 20s后,打印第二个对象的名字。
- ...
- ...
- 5 秒后,打印最后一个对象的名称。
但是下面的代码会累计执行20s,即time = 5s时打印obj 3 & 5,5s后打印obj 1,10s后打印obj 2 & 4。
const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]
function renderTimer(data) {
for (let i = 0; i < data.length; i++) {
const eachName = data[i].name;
const eachTime = data[i].time;
setTimeout(() => {
console.log(eachName);
}, eachTime * 1000);
}
}
renderTimer(data);
我的代码有什么问题?或任何其他方式来实现我想要的结果?
非常感谢!
发生的事情是,程序在 for 循环中竞速,并几乎立即设置了相对于 t=0s 的超时。如果要使用setTimeout(),就得自己累计时间:
const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]
function renderTimer(data) {
var timing = 0;
for (let i = 0; i < data.length; i++) {
const eachName = data[i].name;
timing += data[i].time;
setTimeout(() => {
console.log(eachName);
}, timing * 1000);
}
}
renderTimer(data);
您也可以像这样在递归函数中执行此操作:
const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]
const renderTimer = (data, i = 0) => {
setTimeout(() => {
console.log(data[i].name);
// Call for next data
if(i < data.length - 1)
renderTimer(data, i + 1);
}, data[i].time * 1000);
}
renderTimer(data);
你可以使用 async
/await
and Promise
s
它的工作原理是 await new Promise(...)
停止当前函数直到 Promise 完成
const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]
async function renderTimer(data) {
for (let i = 0; i < data.length; i++) {
const eachName = data[i].name;
const eachTime = data[i].time;
await new Promise(res => {
setTimeout(() => {
console.log(eachName);
// resolve the promise once the log is done
res()
}, eachTime * 100)}
)
// can't arrive here until the setTimeout is finalized
}
}
renderTimer(data);
你可以这样做:
const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]
var time = 0;
function renderTimer(data) {
for (let i = 0; i < data.length; i++) {
const eachName = data[i].name;
time += data[i].time;
const eachTime = time * 1000;
setTimeout(() => {
console.log(eachName);
}, eachTime);
}
}
renderTimer(data);
我有一个不同对象的数组,每个对象包含不同值的时间属性。
我想循环这个数组,里面有一个setTimeout函数,时间就是每个对象的时间属性。
所以我想要的结果是
- 10秒后,打印第一个对象的名称
- 20s后,打印第二个对象的名字。
- ...
- ...
- 5 秒后,打印最后一个对象的名称。
但是下面的代码会累计执行20s,即time = 5s时打印obj 3 & 5,5s后打印obj 1,10s后打印obj 2 & 4。
const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]
function renderTimer(data) {
for (let i = 0; i < data.length; i++) {
const eachName = data[i].name;
const eachTime = data[i].time;
setTimeout(() => {
console.log(eachName);
}, eachTime * 1000);
}
}
renderTimer(data);
我的代码有什么问题?或任何其他方式来实现我想要的结果?
非常感谢!
发生的事情是,程序在 for 循环中竞速,并几乎立即设置了相对于 t=0s 的超时。如果要使用setTimeout(),就得自己累计时间:
const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]
function renderTimer(data) {
var timing = 0;
for (let i = 0; i < data.length; i++) {
const eachName = data[i].name;
timing += data[i].time;
setTimeout(() => {
console.log(eachName);
}, timing * 1000);
}
}
renderTimer(data);
您也可以像这样在递归函数中执行此操作:
const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]
const renderTimer = (data, i = 0) => {
setTimeout(() => {
console.log(data[i].name);
// Call for next data
if(i < data.length - 1)
renderTimer(data, i + 1);
}, data[i].time * 1000);
}
renderTimer(data);
你可以使用 async
/await
and Promise
s
它的工作原理是 await new Promise(...)
停止当前函数直到 Promise 完成
const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]
async function renderTimer(data) {
for (let i = 0; i < data.length; i++) {
const eachName = data[i].name;
const eachTime = data[i].time;
await new Promise(res => {
setTimeout(() => {
console.log(eachName);
// resolve the promise once the log is done
res()
}, eachTime * 100)}
)
// can't arrive here until the setTimeout is finalized
}
}
renderTimer(data);
你可以这样做:
const data = [
{name: "Warm up", timeFormat: "00:10", time: 10},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
{name: "High interval", timeFormat: "00:20", time: 20},
{name: "Low Interval", timeFormat: "00:05", time: 5},
]
var time = 0;
function renderTimer(data) {
for (let i = 0; i < data.length; i++) {
const eachName = data[i].name;
time += data[i].time;
const eachTime = time * 1000;
setTimeout(() => {
console.log(eachName);
}, eachTime);
}
}
renderTimer(data);