You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaScript for循环中添加延迟?邮件发送场景遇异常

问题:JavaScript循环中无法添加延迟实现邮件推送限速

我需要遍历邮箱列表,逐个把邮件发送到后端做新闻邮件推送,为了避免发送过快,想在循环里加暂停,但现在delay方法要等整个循环跑完才会执行。我是JavaScript新手,搞不懂为什么会这样,也不太理解涉及let和阻塞的方案。相关代码如下:

async sendNewsletter (event) {
       
        //Loop over each email and gather the html content followed by sending it to backend
        let counter = 0
        for (const option of this.includedEmailList.options) {
          

            //Call the backend 
            const response = await fetch('url',
            {
                method:'POST',
                credentials:'same-origin',
                headers:{
                    'Content-Type': 'application/json',
                    'Accept' : 'application/json',
                },
                redirect: 'follow',
                body: JSON.stringify({
                    'emailSubject' : this.emailSubject.value,
                    'email' : option.value,
                    'plainTextEmail' : this.emailPlainText.value,
                    'htmlEmail' : this.hiddenHTML.innerHTML}),
            });  

            const responseJson = await response.json();
            console.log(responseJson['status']);
            this.emailSentStatus.innerHTML = responseJson['status'];

            //I need to delay the loop
            counter++;
            this.delay(10000 * counter);
        }
        //Everything has been sent. Leave a message and disable the submission button to prevent 

        emailSentStatus.innerHTML = `all emails have been sent!`;
    }

delay (timeMilliseconds) {
        //To be used in for loop to delay the loop and to slow down
        setTimeout(() => {
            console.log('in delay');
            console.log(timeMilliseconds);}, timeMilliseconds);
    }

解决方案

为什么delay会在循环结束后执行?

核心原因是setTimeout是异步非阻塞的:调用setTimeout时,只是把里面的回调函数放到浏览器的事件队列里,当前的循环会继续执行,不会等定时器到期。而且你现在的delay方法没有返回任何异步对象,就算加了await也无法暂停循环。

怎么改才能让循环逐个延迟执行?

只需要两步:

  1. 把delay改造成返回Promise的方法,这样就能用await来等待延迟完成;
  2. 在循环里用await调用delay,让循环暂停。

另外你之前用counter * 10000会导致延迟时间越来越长(第一次10秒,第二次20秒...),如果只是想每次发送后间隔固定时间,直接用固定值就行。

修改后的完整代码:

async sendNewsletter (event) {
        // 遍历邮箱列表,逐个发送邮件到后端
        for (const option of this.includedEmailList.options) {
            // 调用后端接口发送邮件
            const response = await fetch('url', {
                method:'POST',
                credentials:'same-origin',
                headers:{
                    'Content-Type': 'application/json',
                    'Accept' : 'application/json',
                },
                redirect: 'follow',
                body: JSON.stringify({
                    'emailSubject' : this.emailSubject.value,
                    'email' : option.value,
                    'plainTextEmail' : this.emailPlainText.value,
                    'htmlEmail' : this.hiddenHTML.innerHTML
                }),
            });  

            const responseJson = await response.json();
            console.log(responseJson['status']);
            this.emailSentStatus.innerHTML = responseJson['status'];

            // 等待10秒再执行下一次循环
            await this.delay(10000);
        }
        // 所有邮件发送完成,更新状态(注意加this.)
        this.emailSentStatus.innerHTML = `所有邮件已发送完成!`;
    }

// 改造delay方法,返回Promise以支持await
delay (timeMilliseconds) {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log('延迟结束');
            resolve(); // 延迟完成后通知await继续执行
        }, timeMilliseconds);
    });
}

关键说明

  • await this.delay(10000)会让循环暂停,直到delay里的setTimeout执行完毕并调用resolve();
  • 去掉了counter,如果确实需要每次延迟递增,再重新添加即可;
  • 最后一行的emailSentStatus要加this.,否则会找不到这个实例属性。

内容的提问来源于stack exchange,提问作者jxw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 08:25:31