我如何每秒对数组元素求和
How do I Sum Array elements in every second
我正在尝试按秒计算元素数组的总和。我的数组有20个元素,应该在20秒内求和
我在 for
循环中使用 setTimeout
但它不起作用,循环在第一秒之前完成。无论如何要实现?
for (var o = 0; o < 20; o++) {
setTimeout(function () {
tempPsum += array[o];
}, 1000);
}
是的,循环在第一个 setTimeout
回调发生之前结束。您的代码安排了 20 个回调,这些回调全部发生,一个接一个,一秒后。
你有两个选择:
每一个都比前一个晚一秒,或者
在上一个完成之前不要安排下一个
#1 比较简单,所以让我们这样做:
for (let o = 0; o < 20; o++) {
// ^^^−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
setTimeout(function () {
tempPsum += array[o];
}, 1000 * o);
// ^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−
}
通过将延迟时间乘以 o
,我们得到第一个计时器 0
,第二个计时器 1000
,第三个计时器 3000
...
请注意从 var
到 let
的变化。这样,每个循环迭代都有一个单独的 o
供回调关闭。 (参见 answers here,或...我新书的第 2 章。:-))
如果您不能在您的环境中使用 ES2015+ 功能,您可以使用 setTimeout
的额外参数代替:
for (var o = 0; o < 20; o++) {
setTimeout(function (index) {
// ^^^^^−−−−−−−−−−−
tempPsum += array[index];
// ^^^^^−−−−−−−−−−−
}, 1000 * o, o);
// ^^^^−−^−−−−−−−−−−−−−−−−−−−−−−−
}
这告诉 setTimeout
将您给它的第三个参数作为第一个参数传递给回调。
我认为你可以使用这种方法:
var i = 0;
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
var sum = 0;
function myLoop() {
setTimeout(() => {
sum = sum + arr[i];
console.log(sum);
i++;
if (i < 20) {
myLoop();
}
}, 1000)
}
myLoop();
setTimeout()
的理想用例是当您必须在特定时间范围后执行一次操作时。上面提到的场景需要相同的操作,即在固定时间范围后添加数组元素,所以我相信 setInterval()
会是一个更好的选择。
var array = [1,2,3,4,5];
var tempSum = 0, i = 0;
var intrvl = setInterval( ()=> {
tempSum += array[i++];
console.log(tempSum)
if(i === array.length)
clearInterval(intrvl)
}, 1000)
此答案并未解释问题所在,但提供了其他解决方案的替代方案。您可以添加一个 sleep
函数来在给定的时间内解决承诺,而不是使用索引修改超时。
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
然后在给定的时间内使用 for...of
和 sleep
每次迭代遍历您的数组。
let sum = 0;
for (const number of numbers) {
await sleep(1000);
sum += number;
}
这确实需要将代码放在 async function.
中
const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const numbers = Array.from({length: 20}, () => randomInt(10, 99));
console.log("numbers =", ...numbers);
(async () => {
let sum = 0;
for (const number of numbers) {
await sleep(1000);
console.log(sum, "+", number, "=", sum += number);
}
})();
@TJCrowder 说了为什么你的版本不能用
我会建议另一个解决方案:
另一种方法:使用 setInterval
let numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
let tempPsum = 0
let i = 0
let intervalId = setInterval(function () {
tempPsum += numbers[i];
i = i + 1;
console.log(tempPsum);
if (i == 20) {clearInterval(intervalId)}
}, 1000);
我正在尝试按秒计算元素数组的总和。我的数组有20个元素,应该在20秒内求和
我在 for
循环中使用 setTimeout
但它不起作用,循环在第一秒之前完成。无论如何要实现?
for (var o = 0; o < 20; o++) {
setTimeout(function () {
tempPsum += array[o];
}, 1000);
}
是的,循环在第一个 setTimeout
回调发生之前结束。您的代码安排了 20 个回调,这些回调全部发生,一个接一个,一秒后。
你有两个选择:
每一个都比前一个晚一秒,或者
在上一个完成之前不要安排下一个
#1 比较简单,所以让我们这样做:
for (let o = 0; o < 20; o++) {
// ^^^−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
setTimeout(function () {
tempPsum += array[o];
}, 1000 * o);
// ^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−
}
通过将延迟时间乘以 o
,我们得到第一个计时器 0
,第二个计时器 1000
,第三个计时器 3000
...
请注意从 var
到 let
的变化。这样,每个循环迭代都有一个单独的 o
供回调关闭。 (参见 answers here,或...我新书的第 2 章。:-))
如果您不能在您的环境中使用 ES2015+ 功能,您可以使用 setTimeout
的额外参数代替:
for (var o = 0; o < 20; o++) {
setTimeout(function (index) {
// ^^^^^−−−−−−−−−−−
tempPsum += array[index];
// ^^^^^−−−−−−−−−−−
}, 1000 * o, o);
// ^^^^−−^−−−−−−−−−−−−−−−−−−−−−−−
}
这告诉 setTimeout
将您给它的第三个参数作为第一个参数传递给回调。
我认为你可以使用这种方法:
var i = 0;
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
var sum = 0;
function myLoop() {
setTimeout(() => {
sum = sum + arr[i];
console.log(sum);
i++;
if (i < 20) {
myLoop();
}
}, 1000)
}
myLoop();
setTimeout()
的理想用例是当您必须在特定时间范围后执行一次操作时。上面提到的场景需要相同的操作,即在固定时间范围后添加数组元素,所以我相信 setInterval()
会是一个更好的选择。
var array = [1,2,3,4,5];
var tempSum = 0, i = 0;
var intrvl = setInterval( ()=> {
tempSum += array[i++];
console.log(tempSum)
if(i === array.length)
clearInterval(intrvl)
}, 1000)
此答案并未解释问题所在,但提供了其他解决方案的替代方案。您可以添加一个 sleep
函数来在给定的时间内解决承诺,而不是使用索引修改超时。
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
然后在给定的时间内使用 for...of
和 sleep
每次迭代遍历您的数组。
let sum = 0;
for (const number of numbers) {
await sleep(1000);
sum += number;
}
这确实需要将代码放在 async function.
中const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const numbers = Array.from({length: 20}, () => randomInt(10, 99));
console.log("numbers =", ...numbers);
(async () => {
let sum = 0;
for (const number of numbers) {
await sleep(1000);
console.log(sum, "+", number, "=", sum += number);
}
})();
@TJCrowder 说了为什么你的版本不能用
我会建议另一个解决方案:
另一种方法:使用 setInterval
let numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
let tempPsum = 0
let i = 0
let intervalId = setInterval(function () {
tempPsum += numbers[i];
i = i + 1;
console.log(tempPsum);
if (i == 20) {clearInterval(intervalId)}
}, 1000);