为什么这个 IndexDB 无法识别我的 TotalMoney 对象 Store

问题描述 投票:0回答:1

我是索引数据库的新手,所以这可能是一个简单的修复,但我似乎无法在我的代码中找到任何修复。我正在使用实时服务器来显示它,我面临的问题是它应该在 html 中显示总金额,但它在控制台中给了我一个错误:Here。谢谢您的考虑

下面是我的 dbFunctions。 js

let db;
let request = indexedDB.open("financeManager", 1);




request.onupgradeneeded = function(event){
    db = event.target.result;
    db.createObjectStore("expenses", { keyPath:'id', autoIncrement: true});
    db.createObjectStore("incomes", {keyPath: 'id', autoIncrement: true});
    db.createObjectStore("totalMoney", {keyPath: 'id', autoIncrement: true});

    

};

if(!db.objectStoreNames.contains("totalMoney")){

}


request.onsuccess = function(event){
    db = event.target.result;
};

request.onerror = function(event){
    console.log('error', event.target.errorCode);
};


function updateTotalMoney(updatedTot){
    var transaction = db.transaction(['totalMoney'], 'readwrite');
    var objectStore = transaction.objectStore('totalMoney');

    var getTotal = objectStore.get(1);
    
    getTotal.onsuccess = function(event){
        var data = event.target.result;
        if(data){
            data.total = updatedTot;
            var updateRequest = objectStore.put(data);
            
            updateRequest.onsuccess = function(){
                console.log('Successfully Updated Total');
            }
            updateRequest.onerror = function(){
                console.log("Error with Updating: ", event.target.error);
            }


        } else{
            console.log("no existing totalMoney found, please initialize it first before updating");
        }
        
    }

    getTotal.onerror = function(event){
        console.log("error retrieving Total: ", event.target.error);
    }
}


//GetDatabyname funciton essentially
function getDataByName(storeName, nameValue, callback){
    let transaction = db.transaction([storeName], 'readonly');
    let objectStore = transaction.objectStore(storeName);

    let result = [];

    objectStore.openCursor().onsuccess = function(event){
        let cursor = event.target.result;
        if(cursor){
            if(cursor.value.name === nameValue){
                result.push(cursor.value);
            }
            cursor.continue();
        } else{
            callback(result);
        }
    }
}
//should only be used once, adds totalMoney as a db 
function initializeTotalMoney(total){
    var transaction = db.transaction(['totalMoney'], 'readwrite');
    var objectStore = transaction.objectStore('totalMoney');

    var totalMoney = {
        'total': total
    };
    var request = objectStore.add(totalMoney);

    request.onsuccess = function(event){
        console.log("Successfull");
    }

    request.onerror = function(event){
        console.log("error adding total:" ,event.target.error);
    }
}
function checkAndInitializeTotalMoney(InitialValue){
    var transaction = db.transaction(['totalMoney'], 'readonly');
    var objectStore = transaction.objectStore('totalMoney');

    var getRequest = objectStore.get(1);

    getRequest.onsuccess = function(e){
        if (!e.target.result){
            initializeTotalMoney(InitialValue);
        } else{
            console.log("totalMoney already initialized: ", e.target.result);
        }
    };
    getRequest.onerror = function(e){
        console.log("Error checking tot money: ", e.target.error);
    };
}


//db boilerplate function to add an expense, use addExpense with a name and amount
function addExpense(name, amount, type, interestRate = 0, importance = "N/A"){
    var transaction = db.transaction(['expenses'], 'readwrite');

    var objectStore = transaction.objectStore('expenses');

    var expense = {
        'name': name,
        'amount': amount,
        'interestRate': interestRate,
        'type': type,
        'date': new Date(),
        'importance': importance
    };

    var request = objectStore.add(expense);

    request.onsuccess = function(event){
        console.log('Successfully added Expense');
    }

    request.onerror = function(event){
        console.log('Error adding Expense: ', event.target.error);
    };

}

function addIncome(name, amount, type, interestRate = 0, frequency = "N/A"){
    var transaction = db.transaction(['incomes'], 'readwrite');

    var objectStore = transaction.objectStore('incomes');

    var income = {
        'name': name, 
        'amount': amount,
        'type': type,
        'interestRate': interestRate,
        'date': new Date(),
        'frequency': frequency
    };

    var request = objectStore.add(income);

    request.onsuccess = function(event){
        console.log('Successfully added Income');

    }

    request.onerror = function(event){
        console.log('Error adding Income: ', event.target.error);
    };



}

下面是addIncome。 js 和 addIncome.js html

const dropdownIncome = document.getElementById("dropdownIncome");
const optionForms = document.querySelectorAll(".options");

//submit btns form
const submitOneTime = document.getElementById("submitOneTime");
const submitMonthly = document.getElementById("submitMonthly");
const submitInterest = document.getElementById("submitInterest");

//oneTimeInput
const oneTimeInputLabel = document.getElementById("oneTimeInputLabel");
const oneTimeInput = document.getElementById("oneTimeInput");
//monthlyInput
const monthlyInputLabel = document.getElementById("monthlyInputLabel");
const monthlyInput = document.getElementById("monthlyInput");
const radiosMonthly = document.getElementsByName("radioMonthlyIncome");
//interestInput
const interestInputLabel = document.getElementById("interestInputLabel");
const interestInput = document.getElementById("interestInput");
const interestRateInput = document.getElementById("interestRateInput");

//ultimately displays the selected item of the dropdown
dropdownIncome.addEventListener("change", function(){
    const selectedOption = this.value;
    const showForm = document.getElementById(selectedOption);
    //makes each form invisible
    optionForms.forEach(form => {
        form.style.display = 'none';
    });
    //shows the selected form
    showForm.style.display = "block";

});


//ultimately adds data in input to db and updates totalMoney
submitOneTime.addEventListener("click", function(){
    let oneTimeInputValue = parseFloat(oneTimeInput.value);
    if(isNaN(oneTimeInputValue)){
        alert("Please Enter A Number");
    }
    else{
        //defines expenseName and expenseAmount to be put into addExpense
        var incomeName = oneTimeInputLabel.value;
        var incomeAmount = oneTimeInputValue;

        //adds the name and amount into the db
        addIncome(incomeName, incomeAmount, "oneTime");

        getDataByName("totalMoney", "total", function(data){
            if (data && data[0]){
                var currentTotal = data[0].total;
                var newTotal = currentTotal + oneTimeInputValue;
                updateTotalMoney(newTotal);
            } else{
                console.log("Error retreiving total Money");
            }
        });
        
}});

//ultimately adds data in input to db
submitMonthly.addEventListener("click", function(){
    let monthlyInputValue = parseFloat(monthlyInput.value);
    if(isNaN(monthlyInputValue)){
        alert("Please Enter A Number");
    }
    else{
        for (var i=0, length=radiosMonthly.length; i < length; i++){
            if(radiosMonthly[i].checked){
                var selected = radiosMonthly[i];
                break;
            }
        }

        //defines expenseName and expenseAmount to be put into addExpense
        var incomeName = monthlyInputLabel.value;
        var incomeAmount = monthlyInputValue;
        var incomeFrequency = selected.value;

        //adds the name and amount into the db
        addIncome(incomeName, incomeAmount, "monthly", undefined, incomeFrequency);
        //ADD UPDATETOTALMONEY HERE, DEPENDING ON inCOME FREQUENCY//
    
}});

submitInterest.addEventListener("click", function(){
    let interestInput = parseFloat(interestInput.value);
    let interestRateInput = parseFloat(interestRateInput.value);

    if(isNaN(interestInput) || isNaN(interestRateInput)){
        alert("Please enter numbers for both inputs");

    }
    else{
        var incomeName = interestInputLabel.value;
        var incomeAmount = interestInput;
        var incomeInterest = interestRateInput;

        addIncome(incomeName, incomeAmount, "interest", incomeInterest);

    }
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <select id="dropdownIncome">
        <option value="default">--</option>
        <option value="optionOneTime">
            One-Time Income
        </option>
        <option value="optionMonthly">
            Monthly Income
        </option>
        <option value="optionInterest">
            Interest Income
        </option>


    </select>
    <div id="default" class="options" style="display:none;"> </div>
    <div id="optionOneTime" class = "options" style="display:none;">
        <input type = "text" placeholder="Label" id="oneTimeInputLabel">
        <input type= "text" placeholder="Enter your One-Time Income" id ="oneTimeInput">
        <button id="submitOneTime" class="btnIncome">Submit</button>
        

    </div>
    <div id="optionMonthly" class="options" style="display:none;">
        <input type = "text" placeholder="Label" id="monthlyInputLabel">
        <input type="text" placeholder="Enter your Monthly Income" id="monthlyInput">
        <button id="submitMonthly" class="btnIncome">Submit</button>
        <input type="radio" name="radioMonthlyIncome" id="Weekly">Weekly
        <input type="radio" name="radioMonthlyIncome" id="BiWeekly">Bi-Weekly
        <input type="radio" name="radioMonthlyIncome" id="Monthly">Monthly

    </div>
    <div id="optionInterest" class="options" style="display:none;">
        <input type="text" placeholder="Label" id="interestInputLabel">
        <input type="text" placeholder="Enter your Base Interest Income" id="interestInput">
        <input type="text" placeholder="Enter your Interest Rate" id="interestRateInput">
        <button id="submitInterest" class="btnIncome">Submit</button>
        
    
    </div>

<script src="dbFunctions.js"></script>
<script src="addIncome.js"></script>
</body>
</html>
以下是附加费用。 js 和 addExpenses.分别为 html 文件。
const dropdownExpenses = document.getElementById("dropdownExpenses");
const optionForms = document.querySelectorAll(".options");
//submit btns form
const submitMonthly = document.getElementById("submitMonthly");
const submitOneTime = document.getElementById("submitOneTime");
const submitMortgage = document.getElementById("submitMortgage");

//oneTimeInput
const oneTimeInputLabel = document.getElementById("oneTimeInputLabel");
const oneTimeInput = document.getElementById("oneTimeInput");
const radiosOneTime = document.getElementsByName("radioOneTime");
//monthlyInput
const monthlyInputLabel = document.getElementById("monthlyInputLabel");
const monthlyInput = document.getElementById("monthlyInput");
const radiosMonthly = document.getElementsByName("radioMonthly");
//mortgageInput
const mortgageInputLabel = document.getElementById("mortgageInputLabel");
const mortgageBasePayInput = document.getElementById("mortgageBasePayInput");
const mortgageInterestRateInput = document.getElementById("mortgageInterestRateInput");




//ultimately displays the selected item of the dropdown
dropdownExpenses.addEventListener("change", function (){
    const selectedOption = this.value;
    const showForm = document.getElementById(selectedOption);

    //makes each form invisible
    optionForms.forEach(form => {
        form.style.display = 'none';
    });
    //shows the form selected
    showForm.style.display = "block";
});
//ultimately adds data in input field to db, and updates total money
submitOneTime.addEventListener("click", function(){
    let oneTimeInputValue = parseFloat(oneTimeInput.value);
    if(isNaN(oneTimeInputValue)){
        alert("Please Enter A Number");
    }
    else{



        for (var i=0, length=radiosOneTime.length; i < length; i++){
            if(radiosOneTime[i].checked){
                var selected = radiosOneTime[i];
                break;
            }
        }


        //defines expenseName and expenseAmount to be put into addExpense
        var expenseName = oneTimeInputLabel.value;
        var expenseAmount = oneTimeInputValue;
        var expenseImportance = selected.value;
        

        //adds the name and amount into the db
        addExpense(expenseName, expenseAmount, "oneTime", undefined, expenseImportance);

        getDataByName("totalMoney", "total", function(data){
            if (data && data[0]){
                var currentTotal = data[0].total;
                var newTotal = currentTotal - oneTimeInputValue;
                updateTotalMoney(newTotal);
            } else{
                console.log("Error retreiving total Money");
            }
        });


        
}});
//ultimately adds data in input field to db
submitMonthly.addEventListener("click", function(){
    let monthlyInputValue = parseFloat(monthlyInput.value);
    if(isNaN(monthlyInputValue)){
        alert("Please enter a Number");
    }
    else{

        for (var i=0, length=radiosMonthly.length; i < length; i++){
            if(radiosMonthly[i].checked){
                var selected = radiosMonthly[i];
                break;
            }
        }

        var expenseName = monthlyInputLabel.value;
        var expenseAmount = monthlyInputValue;
        var expenseImportance = selected.value;

        addExpense(expenseName, expenseAmount, "monthly", undefined, expenseImportance);
    }
});

submitMortgage.addEventListener("click", function(){
    let mortgageBasePayInputValue = parseFloat(mortgageBasePayInput.value);
    let mortgageInterestRateInputValue = parseFloat(mortgageInterestRateInput.value);

    if(isNaN(mortgageBasePayInputValue) || isNaN(mortgageInterestRateInputValue)){
        alert("Please enter numbers for both inputs");

    }
    else{
        var expenseName = mortgageInputLabel.value;
        var expenseAmount = mortgageBasePayInputValue;
        var expenseInterest = mortgageInterestRateInputValue;

        addExpense(expenseName, expenseAmount, "mortgage", expenseInterest, undefined);

    }
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href = "addExpenses.css">
    <title>Document</title>
</head>
<body>
    <a href="financetracker.html">
        <p>Go Back</p>
    </a>
    <select id="dropdownExpenses">
        <option value="default">--</option>
        <option value="optionMonthly">
            Monthly Expense
        </option>
        <option value = "optionOneTime">
            One-Time Expense
        </option>
        <option value = "optionMortgage">
            Mortgage Expense
        </option>

    </select>

    <div id="default" style="display:none;" class="options"> </div>
    <div id="optionMonthly" style="display:none;" class="options">
        <input type="text" placeholder="Label" id="monthlyInputLabel">
        <input type="text" placeholder="Select A Monthly Expense Amount" id="monthlyInput">
        <button id="submitMonthly" class="btnExpenses">Submit</button>
        <input type="radio" name="radioMonthly" id="Luxury">Luxury
        <input type="radio" name="radioMonthly" id="Necessity">Necessity
        <input type="radio" name="radioMonthly" id="Favorable">Favorable
    </div>
    <div id="optionOneTime" style = "display:none;" class="options">
        <input type="text" placeholder="Label" id="oneTimeInputLabel">
        <input type="text" placeholder="Select a One-Time Expense" id="oneTimeInput">
        <button id="submitOneTime" class="btnExpenses">Submit</button>
        <input type="radio" name="radioOneTime" id="Luxury">Luxury
        <input type="radio" name="radioOneTime" id="Necessity">Necessity
        <input type="radio" name="radioOneTime" id="Favorable">Favorable
    </div>
    <div id="optionMortgage" style="display:none;" class="options">
        <input type="text" placeholder="Label" id="mortgageInputLabel">
        <input type="text" placeholder="Select your base monthly Mortgage Expense" id="mortgageBasePayInput">
        <input type="text" placeholder="Select your monthly interest rate" id="mortgageInterestRateInput">
        <button id="submitMortgage" class="btnExpenses">Submit</button>
        
    </div>
    <script src="dbFunctions.js"></script>
    <script src="addExpenses.js"></script>
</body>
</html>

下面是我的财务追踪器。 js,. CSS 和 . html

//input daily expenses, incldues consistent expenses as well as one time purchases
//include monthly expenses as well as any overarching expenses
//categorize  expenses: necessities, luxuries, one time expenses etc etc
//include wages, put in hours of work and output total profit
//then, visualize the data with various charts and tracking
//finally, for now suggest ways to cut spending


//want to calculate Income and Expenses on the daily, except for instant payments/debts.
//make choice btw implementing flat monthly rates on graph with instant or over time.
//prob over time since it would fit better on this big top max of budget/ income


//manually set totalMoney (usually to 0), then log that value in the db



document.addEventListener("DOMContentLoaded", function(){
    var totalMoney = 10000000;
    checkAndInitializeTotalMoney(totalMoney);
    //puts commas in totalMoney as well as updates text box
    function displayTotalMoney(total){
        console.log("Display Total Money is being called");
        var totalMoneyS = total.toString(); 
        for (let i = totalMoneyS.length - 3; i > 0; i-=3){
            totalMoneyS = totalMoneyS.slice(0, i) + ',' + totalMoneyS.slice(i);
        }
        
        document.getElementById("moneyAmount").textContent = totalMoneyS;
    }
    //takes the value of total in totalMoney and runs displayTotalMoney there
    function assignMoneyUse(data){
        //checks if data is not empty and that it has at least one element
        if(data && data[0]){
            displayTotalMoney(data[0].total);
        }else{
            console.log("no data found for total in totalMoney");
        }
    }



   //gets db data for totalMoney
    getDataByName("totalMoney", "total", assignMoneyUse);
    


});
.viewButtons{
    width: 350px;
    height: 200px;
    font-size: 50px;
    font-family: 'Times New Roman', Times, serif;
    border-radius: 10px;
}


.balanceBottomLine{
    position: relative;
    top: 200px;
    left: 100px;
    width: 1500px;
    height: 5px;
    background-color: black;
}

#addExpenses{
    position: absolute;
    top:100px;
    left:100px;
    


}

#addIncome{
    position: absolute;
    top: 100px;
    left: 500px;
   
}

#statistics{
    position: absolute;
    top: 100px;
    left: 900px;
}

.dataVisBox{
    position: relative;
    top: 600px;
    left:125px;
    width:1500px;
    height:1000px;
    border:5px solid black;
    
}

.moneyHave{
    position: absolute;
    top: -110px;
    font-size: 100px;
    font-family: Arial, Helvetica, sans-serif;
}

.moneyHave p{
    display: inline;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="financetracker.css">
</head>
<body>
    <div class="balanceBottomLine"> 
    <a href="addExpenses.html">
    <button id="addExpenses" class="viewButtons">Add Expenses </button>
    </a>
    <a href = "addIncome.html">
    <button id="addIncome" class="viewButtons">Add Income</button>
    </a>
    <a href = "checkStatistics.html">
    <button id="statistics" class="viewButtons">Check Statistics</button>
    </a>
    <div class="moneyHave">
        <p class="currencySign">$</p> <p class="moneyAmount" id="moneyAmount">000,000,000,000</p>
        
        </div>
</div>
<div class="dataVisBox">


</div>
    <script src="dbFunctions.js"></script>
    <script src="financetracker.js"></script>
</body>
</html>

javascript html css indexeddb
1个回答
0
投票

此处错误的原因是 dbFunctions.js 文件中的 db 变量在 checkAndInitializeTotalMoney() 方法中显示为未定义。

解决方案1

解决方案1:您可以通过使用Promise和await结构来解决这个问题,这样首先访问db,然后访问checkAndInitializeTotalMoney()方法。这是第一个解决方案。

其中: dbFunctions.js 和finanstracker.html

let db;
let request = indexedDB.open("financeManager", 1);


function openDb() {
    return new Promise((resolve, reject) => {
        request.onupgradeneeded = function(event) {
            db = event.target.result;
            db.createObjectStore("expenses", { keyPath: 'id', autoIncrement: true });
            db.createObjectStore("incomes", { keyPath: 'id', autoIncrement: true });
            db.createObjectStore("totalMoney", { keyPath: 'id', autoIncrement: true });
            if (!db.objectStoreNames.contains("totalMoney")) {
                
            }
        };

        request.onsuccess = function(event) {
            db = event.target.result;
            console.log("is db ok: " + db);
            resolve(db); //if db open success then accept and return
        };

        request.onerror = function(event) {
            console.log('error', event.target.errorCode);
            reject(event.target.errorCode); 
        };
    });
}

async function init(totalMoney) {
    try {
        await openDb();
        checkAndInitializeTotalMoney(totalMoney);
    } catch (error) {
        console.error("When db try to open error: ", error);
    }
}


function initializeTotalMoney(total){
    var transaction = db.transaction(['totalMoney'], 'readwrite');
    var objectStore = transaction.objectStore('totalMoney');

    var totalMoney = {
        'total': total
    };
    var request = objectStore.add(totalMoney);

    request.onsuccess = function(event){
        console.log("Successfull");
    }

    request.onerror = function(event){
        console.log("error adding total:" ,event.target.error);
    }
}


function checkAndInitializeTotalMoney(InitialValue) {

  console.log("db: " + db)

  var transaction = db.transaction(['totalMoney'], 'readonly');
  var objectStore = transaction.objectStore('totalMoney');

  var getRequest = objectStore.get(1);

  getRequest.onsuccess = function(e){
      if (!e.target.result){
          initializeTotalMoney(InitialValue);
      } else{
          console.log("totalMoney already initialized: ", e.target.result);
      }
  };
  getRequest.onerror = function(e){
      console.log("Error checking tot money: ", e.target.error);
  };


}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="financetracker.css">
</head>
<body>
    <div class="balanceBottomLine"> 
    <a href="addExpenses.html">
    <button id="addExpenses" class="viewButtons">Add Expenses </button>
    </a>
    <a href = "addIncome.html">
    <button id="addIncome" class="viewButtons">Add Income</button>
    </a>
    <a href = "checkStatistics.html">
    <button id="statistics" class="viewButtons">Check Statistics</button>
    </a>
    <div class="moneyHave">
        <p class="currencySign">$</p> <p class="moneyAmount" id="moneyAmount">000,000,000,000</p>
        
        </div>
</div>
<div class="dataVisBox">


</div>
    <script src="dbFunctions.js"></script>
    <script src="financetracker.js"></script>
</body>
</html>

并像这样调用financetracker.js中的init()方法:

document.addEventListener("DOMContentLoaded", function(){
    var totalMoney = 10000000;
    init(totalMoney);

});

解决方案2

解决方案2:如果您想要不太复杂的结构;您可能希望在每次数据库操作之前打开数据库并执行您的操作。

dbFunctions.js

    let db;
    let request = indexedDB.open("financeManager", 1);

    request.onupgradeneeded = function(event){
        
        db = event.target.result;
        db.createObjectStore("expenses", { keyPath:'id', autoIncrement: true});
        db.createObjectStore("incomes", {keyPath: 'id', autoIncrement: true});
        db.createObjectStore("totalMoney", {keyPath: 'id', autoIncrement: true});

        
        if(!db.objectStoreNames.contains("totalMoney")){

        }
        
    };



    request.onsuccess = function(event){
        db = event.target.result;
        console.log("is db ok: " + db);
    
    };

    request.onerror = function(event){
        console.log('error', event.target.errorCode);
    };

    //should only be used once, adds totalMoney as a db 
    function initializeTotalMoney(total){
        var transaction = db.transaction(['totalMoney'], 'readwrite');
        var objectStore = transaction.objectStore('totalMoney');

        var totalMoney = {
            'total': total
        };
        var request = objectStore.add(totalMoney);

        request.onsuccess = function(event){
            console.log("Successfull");
        }

        request.onerror = function(event){
            console.log("error adding total:" ,event.target.error);
        }
    }

    function checkAndInitializeTotalMoney(db, InitialValue) {
        //OPEN HERE AGAIN
        const request = window.indexedDB.open("financeManager");
        request.onsuccess = (event) => {
        const db = event.target.result;

    console.log("db: " + db)

    var transaction = db.transaction(['totalMoney'], 'readonly');
    var objectStore = transaction.objectStore('totalMoney');

    var getRequest = objectStore.get(1);

    getRequest.onsuccess = function(e){
        if (!e.target.result){
            initializeTotalMoney(InitialValue);
        } else{
            console.log("totalMoney already initialized: ", e.target.result);
        }
    };
    getRequest.onerror = function(e){
        console.log("Error checking tot money: ", e.target.error);
    };

    }
    }

并像这样调用financetracker.js中的init()方法:

document.addEventListener("DOMContentLoaded", function(){
    var totalMoney = 10000000;
    checkAndInitializeTotalMoney(totalMoney);
});

尝试这两种解决方案后,控制台输出:

© www.soinside.com 2019 - 2024. All rights reserved.