javascript - Javascript 中的线程安全?

标签 javascript asp.net-ajax concurrency

我有一个名为 save() 的函数,该函数收集页面上的所有输入,并对服务器执行 AJAX 调用以保存用户工作的状态。

save() 当前在用户点击保存按钮时被调用,或者执行一些其他需要我们在服务器上拥有最新状态的操作(例如从页面生成文档)。

我添加了每隔一段时间自动保存用户工作的功能。首先,我想防止自动保存和用户生成的保存同时运行。所以我们有以下代码(我削减了大部分代码,这不是 1:1,但应该足以让这个想法得到理解):

var isSaving=false;
var timeoutId;
var timeoutInterval=300000;
function save(showMsg)
{
  //Don't save if we are already saving.
  if (isSaving)
  { 
     return;
  }
  isSaving=true;
  //disables the autoSave timer so if we are saving via some other method
  //we won't kick off the timer.
  disableAutoSave();

  if (showMsg) { //show a saving popup}
  params=CollectParams();
  PerformCallBack(params,endSave,endSaveError);

}
function endSave()
{  
    isSaving=false;
    //hides popup if it's visible

    //Turns auto saving back on so we save x milliseconds after the last save.
    enableAutoSave();

} 
function endSaveError()
{
   alert("Ooops");
   endSave();
}
function enableAutoSave()
{
    timeoutId=setTimeOut(function(){save(false);},timeoutInterval);
}
function disableAutoSave()
{
    cancelTimeOut(timeoutId);
}

我的问题是这段代码是否安全?主流浏览器一次只允许一个线程执行吗?

我的一个想法是,如果我们是自动保存的,那么用户点击保存却得不到任何响应会更糟(而且我知道如何修改代码来处理这个问题)。有人在这里看到任何其他问题吗?

最佳答案

浏览器中的 JavaScript 是单线程的。您在任何时间点都只会参与一个功能。功能将在输入下一个功能之前完成。您可以依靠这种行为,因此如果您在 save() 函数中,在当前函数完成之前您将永远不会再次进入它。

当您有异步服务器请求(或 setTimeouts 或 setIntervals)时,这有时会让人感到困惑(但仍然如此),因为那时感觉您的函数是 interleaved .他们不是。

在您的情况下,虽然两个 save() 调用不会相互重叠,但您的自动保存和用户保存可能背靠背发生。

如果您只想至少每 x 秒保存一次,您可以在保存函数上执行 setInterval 并忘记它。我认为不需要 isSaving 标志。

我认为您的代码可以大大简化:

var intervalTime = 300000;
var intervalId = setInterval("save('my message')", intervalTime);
function save(showMsg)
{
  if (showMsg) { //show a saving popup}
  params=CollectParams();
  PerformCallBack(params, endSave, endSaveError);

  // You could even reset your interval now that you know we just saved.
  // Of course, you'll need to know it was a successful save.
  // Doing this will prevent the user clicking save only to have another
  // save bump them in the face right away because an interval comes up.
  clearInterval(intervalId);
  intervalId = setInterval("save('my message')", intervalTime);
}

function endSave()
{
    // no need for this method
    alert("I'm done saving!");
}

function endSaveError()
{
   alert("Ooops");
   endSave();
}

关于javascript - Javascript 中的线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2253586/

相关文章:

javascript - 查明 Android 浏览器是在应用程序中运行还是自行运行

javascript - 访问 html 表中的行

multithreading - 多线程的目的是增加CPU使用率吗?

javascript - 带有 Ajax 按钮的 Asp.net MVC 从数据库中检索数据

c# - Parallel.ForEach 不断产生新线程

java - 对 ReentrantReadWriteLock#tryLock 失败的 jcstress 测试感到困惑

javascript - 像 JavaScript 一样转义 a​​s3 中的字符

javascript - 表格单元格上的 ng-change 更新所有单元格

c# - 使用 UPDATE PANEL 时,应用程序不显示 javascript 消息

javascript - 我应该学习 ASP.NET AJAX、jQuery 还是两者都学?