如何阻止正在运行的forEach循环不执行两次?

时间:2019-04-10 10:47:11

标签: javascript node.js

我有一个名为sendMail的功能,该功能可以获取一些电子邮件地址并向该用户发送邮件。

通过在用户界面中单击按钮来调用此功能。

但是,如果多次调用此功能,则电子邮件也会发送多次。

我想阻止该功能在它已经运行时不再执行。我的意思是,如果用户调用它,我想阻止该按钮以防止用户再次单击并再次调用此函数。

这就是发送邮件的路径

routes.get('/sendMail', (req, res)=>{     
    db.find({ subscribed: true}, (err, result) => { 

        if(err){
            throw err;
       }else{                 
            result.forEach(function(subscriber, index){                                
                setTimeout(function() {
                    sendMail(subscriber);                    
                }, 3000*index) 

            });
            res.render('records.ejs', {root: '.'}); 
        }
    });
});

一旦js是单线程并且假定我两次调用sendMail,那么此函数应该仅在当前执行完成后才再次执行吗?

很抱歉,这是一个新手问题。欢迎任何博客文章,教程等。

2 个答案:

答案 0 :(得分:2)

  

我想阻止按钮,以防止用户再次单击并   再次调用此函数。

一种常用的非常简单的方法是在单击按钮后将其禁用。这是一个示例:

// Get button reference and set up click handler
document.querySelector("button").addEventListener("click", function(){
  // Here's where you'd call your sendMail function
  // sendMail();
  console.log("send mail has been called");
  
  // Then disable the button:
  this.disabled = true;
});
<button>Click Me</button>

另一个更强大的解决方案是在调用事件处理程序后将其删除。您仍然希望禁用该按钮以获得更好的用户体验。

// Get button reference and set up click handler
document.querySelector("button").addEventListener("click", handleButtonClick);

function handleButtonClick(){
  // Here's where you'd call your sendMail function
  // sendMail();
  console.log("send mail has been called");
  
  // Then remove the handler and disable the button
  this.removeEventListener("click", handleButtonClick);
  this.disabled = true;
}
<button>Click Me</button>

答案 1 :(得分:1)

你可以有这样的东西

.title {
    text-indent: 100%;
}

然后它将不会再呼叫同一订户,直到它解决为止。只要知道如何处理发生错误的情况,否则您将得到永远不会被删除的订户。您还可以在其中放置时间戳记,而不是true / false,并且仅在时间戳记存在且不超过10分钟的情况下接受它(以避免永久阻止用户行为)。

但是,如果您具有多个实例的负载均衡器,并且由于不同的服务可以使用它多次调用端点,则此方法将不起作用。在这种情况下,您将需要Redis这样的行为。