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

jQuery/JavaScript顺序更新锁变量实现及表单耗时统计问询

How to Implement a Lock Variable for Accurate Form Timer Updates in jQuery

Got it, let's solve this timer accuracy problem with a lock variable. The core issue here is that your multiple bound events (focusin, input, button clicks) can fire nearly at the same time, causing race conditions where your timer logic runs out of sync. A simple lock will prevent overlapping executions and keep your timing data reliable.

Step 1: Initialize the Lock

Instead of using a global variable (which can cause conflicts with other code), we'll store the lock state directly on the form element using jQuery's data() method—this keeps things clean and scoped to your specific form.

// Initialize the lock when your page/form loads
$("#application-form").data("timerLocked", false);

Step 2: Modify timerUpdate with Lock Logic

Update your timerUpdate function to check the lock before executing, and ensure it always unlocks even if an error occurs (using try/finally):

function timerUpdate() {
  const $form = $("#application-form");
  const isLocked = $form.data("timerLocked");

  // If the timer is already updating, exit immediately
  if (isLocked) return;

  // Lock the timer to block concurrent updates
  $form.data("timerLocked", true);

  try {
    // --- Your existing timer logic goes here ---
    // Example: Calculate elapsed time, update hidden inputs, etc.
    const currentTime = Date.now();
    const startTime = $form.data("timerStartTime") || currentTime;
    const elapsed = Math.floor((currentTime - startTime) / 1000);
    $form.find("#elapsed-time").val(elapsed);
    $form.data("timerStartTime", startTime); // Persist start time
  } finally {
    // Always unlock, even if an error happens in your logic
    $form.data("timerLocked", false);
  }
}

Step 3: Secure finaliseTimer as Well

Since finaliseTimer is the end-of-form action, you'll want to lock the timer here too to prevent last-minute updates during finalization:

function finaliseTimer() {
  const $form = $("#application-form");
  // Lock to block any pending timer updates
  $form.data("timerLocked", true);

  try {
    // --- Your final timer logic goes here ---
    // Example: Calculate total time, send to server, submit form
    const totalTime = Math.floor((Date.now() - $form.data("timerStartTime")) / 1000);
    $form.find("#total-form-time").val(totalTime);
    
    // Submit the form or send data to your backend
    $form.submit();
  } finally {
    // Optional: Keep locked after finalization if you don't want further updates
    // $form.data("timerLocked", false);
  }
}

Bonus: Handle Async Logic (If Needed)

If your timer logic includes asynchronous operations (like saving progress to a server via AJAX), move the unlock to the async callback to avoid releasing the lock too early:

function timerUpdate() {
  const $form = $("#application-form");
  if ($form.data("timerLocked")) return;

  $form.data("timerLocked", true);

  // Example async AJAX call to save timer progress
  $.ajax({
    url: "/api/save-timer",
    method: "POST",
    data: { elapsedTime: $form.find("#elapsed-time").val() }
  })
  .done(function(response) {
    // Handle success
  })
  .fail(function(error) {
    // Handle error (e.g., log or notify user)
  })
  .always(function() {
    // Unlock only after the async operation completes
    $form.data("timerLocked", false);
  });
}

Extra Tip: Combine with Debouncing

For events like input (which fires on every keystroke), adding debouncing alongside the lock can reduce unnecessary executions while still preventing race conditions. Here's how to do it with a debounce utility (you can use Lodash's _.debounce or a custom implementation):

// Debounced and locked timer update (wait 200ms after last input)
const debouncedTimerUpdate = _.debounce(function() {
  const $form = $("#application-form");
  if ($form.data("timerLocked")) return;

  $form.data("timerLocked", true);
  try {
    // Your timer logic here
  } finally {
    $form.data("timerLocked", false);
  }
}, 200);

// Update your event binding to use the debounced function
$("#application-form").on("focusin input", "input[type=text]", debouncedTimerUpdate);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:06:51