我如何每秒对数组元素求和

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. 每一个都比前一个晚一秒,或者

  2. 在上一个完成之前不要安排下一个

#1 比较简单,所以让我们这样做:

for (let o = 0; o < 20; o++) {
//   ^^^−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
   setTimeout(function () {
       tempPsum += array[o];
   }, 1000 * o);
//        ^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−
}

通过将延迟时间乘以 o,我们得到第一个计时器 0,第二个计时器 1000,第三个计时器 3000...

请注意从 varlet 的变化。这样,每个循环迭代都有一个单独的 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...ofsleep 每次迭代遍历您的数组。

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);