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

IndexedDB报错:Uncaught TypeError: Cannot read property 'transaction' of undefined 问题排查求助

Fix: Uncaught TypeError: Cannot read property 'transaction' of undefined

Let's break down exactly what's going wrong here and fix it step by step:

1. The Core Issue: Scope Mismatch

Looking at your code structure, you have an IIFE that declares let DB; locally, but your conectDB function is defined outside this IIFE. When conectDB runs and assigns DB = openConection.result;, it's actually setting a global DB variable—not the local one inside your IIFE. That means when createNewClient tries to use DB.transaction(), it's referencing the uninitialized local DB (which is undefined), hence the error.

2. Secondary Issue: Async Database Connection

IndexedDB connections are asynchronous. Even if you fix the scope, if a user submits the form before the onsuccess callback fires, DB will still be undefined when createNewClient runs.

Full Solution

Here's the corrected code with both issues fixed:

(function(){
  let DB;
  const form = document.querySelector('#form');

  document.addEventListener('DOMContentLoaded', () => { 
    conectDB();
    // We'll add a check in the submit handler for DB readiness
    form.addEventListener('submit', validates);
  });

  // Move conectDB INSIDE the IIFE so it can access the local DB variable
  function conectDB() {
    const openConection = window.indexedDB.open('crm', 4);

    openConection.onerror = function() {
      console.error('Error connecting to IndexedDB');
      alertMessage('Failed to connect to database', 'error');
    }

    openConection.onsuccess = function() {
      DB = openConection.result;
      console.log('Successfully connected to IndexedDB');
    }

    // Critical: Handle database upgrades to ensure the 'crm' object store exists
    openConection.onupgradeneeded = function(e) {
      const db = e.target.result;
      // Create the 'crm' object store with 'id' as the primary key
      db.createObjectStore('crm', { keyPath: 'id' });
    }
  }

  function validates(e) {
    e.preventDefault();

    // First, check if the database is ready
    if (!DB) {
      alertMessage('Database is still loading—please wait a moment', 'error');
      return;
    }

    const name = document.querySelector('#name').value;
    const email = document.querySelector('#email').value;
    const phone = document.querySelector('#phone').value;
    const company = document.querySelector('#company').value;

    if(name === '' || email === '' || phone === '' || company === '' ) {
      alertMessage('All Fields are required', 'error');
      return;
    }

    const client = {
      name,
      email,
      phone,
      company,
      id: Date.now()
    }
    createNewClient(client);
  }

  function createNewClient(client) {
    const transaction = DB.transaction(['crm'], 'readwrite');
    const objectStore = transaction.objectStore('crm');
    objectStore.add(client);

    transaction.onerror = function() {
      alertMessage('Failed to add client—please check your input', 'error')
    }

    transaction.oncomplete = function() {
      alertMessage('Client Added ');
      setTimeout(() => {
        window.location.href = 'index.html';
      }, 3000);
    }
  }

  function alertMessage(msg, type){
    const alert = document.querySelector('.alert');
    if(!alert) {
      const divAlert = document.createElement('div');
      divAlert.classList.add('px-4', 'py-3', 'rounded', 'max-w-lg', 'mx-auto', 'mt-6', 'text-center', 'border', 'alert');

      if(type === 'error') {
        divAlert.classList.add('bg-red-100', 'border-red-400', 'text-red-700');
      } else {
        divAlert.classList.add('bg-green-100', 'border-green-400', 'text-green-700');
      }

      divAlert.textContent = msg;
      form.appendChild(divAlert);

      setTimeout(() => {
        divAlert.remove();
      }, 3000);
    }
  }
})();

Key Fixes Explained:

  • Scope Correction: By moving conectDB inside the IIFE, it now references the same DB variable that createNewClient uses—no more global/local mismatch.
  • Async Readiness Check: The validates function now checks if DB exists before proceeding, preventing errors from early form submissions.
  • onupgradeneeded Handler: This ensures your crm object store is created when the database is first opened or upgraded. Without this, you'd get errors trying to access a non-existent store.

Alternative: Bind Submit Event Only After DB Connects

If you want to prevent users from even submitting the form until the DB is ready, you can move the form.addEventListener call into the onsuccess callback:

openConection.onsuccess = function() {
  DB = openConection.result;
  console.log('Successfully connected to IndexedDB');
  // Only enable form submission once DB is ready
  form.addEventListener('submit', validates);
}

This way, the submit event isn't even attached until the database is fully initialized.

内容的提问来源于stack exchange,提问作者Alejandro Vargas Madrid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 16:17:48