iT邦幫忙

0

db.transaction的擺放位置

我在嘗試對indexedDB資料庫做刪除的練習.
關於"db.transaction的擺放位置"有點疑問.
想請各位db.transaction是不是不能直接在:
$(function(){
...(這裡面直接建立??)...
var transaction = db.transaction("customer","readwrite");
});

1.先利用以下範例,對indexedDB建立資料庫

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>indexedDB建立資料</title>
    <style>
        div{border:2px dotted #ff0000; padding:5px;}
    </style>
    <script>
        var db,str;
        $(function(){
            //1.判斷支援indexedDB
            window.indexedDB = window.indexedDB || window.mozIndexedDB || webkitIndexedDB || window.msIndexedDB;
            if(!window.indexedDB){
                alert("您的瀏覽器不支援indexedDB");
            }

            //2.開啟資料庫
            var req = window.indexedDB.open("MyDatabase");

            //處理open觸發的success和error事件
            req.onsuccess = function(evt){
                //this:IDBOpenDBRequest
                db = this.result;                
                str = "MyDatabase 建立完成"
                    + ">狀態:" + this.readyState
                    + ">版本:" + db.version
                    + "<br>";
                $("div").html(str);
            };

            req.onerror = function(evt){
                $('div').html("開啟資料庫錯誤:" + evt.target.errorCode);
            };

            //3.處理onupgradeneeded事件
            req.onupgradeneeded = function(event){
                var objectStore = event.target.result.createObjectStore("customer",{keyPath:"user_id"});
                objectStore.createIndex("name","name",{unique:false});                
            };
            
            $("#addbtn").click(function(){
                add_click('add');
            });

            $("#putbtn").click(function(){
                add_click('put');
            });

            function add_click(add_way){
                /*
                    4.開啟交易            
                */
                var transaction = db.transaction("customer","readwrite");

                //定義transaction的"成功和失敗事件".
                transaction.oncomplete = function(event){
                    str+="交易成功<br>";
                    $("div").html(str);
                };

                //在帳號不變的狀況下,新增兩次,就會出現交易錯誤
                transaction.onerror = function(event){$("div").html("交易失敗");};
                
                //5.利用transaction取得objectStore
                store = transaction.objectStore("customer");

                //6.新增資料
                if(add_way=="add")
                    request = store.add({user_id:$('#user_id').val(),name:$("#name").val()});
                else
                    request = store.put({user_id:$('#user_id').val(),name:$("#name").val()});

                //7.定義add/put成功或失敗事件
                request.onsuccess = function(e){
                    str += "新增資料成功<br>";
                    $("div").html(str);
                }

                request.onerror = function(e){
                    $("div").html("新增資料失敗:" + e.target.error);
                }
            }
        });
    </script>
</head>
<body>
    帳號: <input type="text" id="user_id"><br>
    姓名: <input type="text" id="name"><br>
    <button id="addbtn">新    增</button>
    <button id="putbtn">新增/更新</button>
    <div id="message"></div>
</body>
</html>

2.以下是我出現錯誤的程式碼.
錯誤訊息為:Uncaught TypeError: Cannot read property "transaction"...

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IndexedDB刪除資料</title>
    <style>
        div{border:2px dotted #ff0000; padding:5px;}
    </style>
    <script>
        var db,str;
        $(function(){
            window.indexedDB = window.indexedDB || widow.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

            if(!window.indexedDB)
                alert("不支援IndexedDB");

            //1.開啟資料庫
            var req = window.indexedDB.open("MyDatabase");
            
            req.onsuccess = function(evt){
                db = this.result;
                str = "MyDatabase 成功開啟." + "<br>";
                $('div').html(str);
            };
            req.onerror = function(evt){
                $('div').html("無法連結資料庫!<br>" + evt.target.errorCode);
            }
            //處理onupgradeneeded事件(若無資料庫,就會執行onupgradeneeded事件)
            req.onupgradeneeded = function(event){                
                var objectStore = event.target.result.createObjectStore("customer",{keyPath:"user_id"});
                objectStore.createIndex("name","name",{unique:false});
            };

            var transaction = db.transaction("customer","readwrite");
            transaction.oncomplete = function(event){
                str+="交易成功<br>";
                $("div").html(str);
            };
            transaction.onerror = function(event){$("div").html("交易失敗");};
            //取得objectStore
            store = transaction.objectStore("customer");
            transaction.oncomplete = function(event){
                str+="交易成功<br>";
                $("div").html(str);
            };
            transaction.onerror = function(event){$("div").html("交易失敗");};
            //4.刪除資料
            var req = store.delete("A0001");
            req.onsuccess = function(e){
                str += "資料刪除成功." + "A0001已被刪除<br>";
                $('div').html(str);
            };
            req.onerror = function(e){
                $('div').html("資料刪除失敗.");
            };            
        });
    </script>
</head>
<body>
    <div id="message"></div>    
</body>
</html>

3.但我使用Button的click事件,做上面的動作就可以成功.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IndexedDB刪除資料</title>
    <style>
        div{border:2px dotted #ff0000; padding:5px;}
    </style>
    <script>
        var db,str;
        $(function(){
            window.indexedDB = window.indexedDB || widow.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

            if(!window.indexedDB)
                alert("不支援IndexedDB");

            //1.開啟資料庫
            var req = window.indexedDB.open("MyDatabase");
            
            req.onsuccess = function(evt){
                db = this.result;
                str = "MyDatabase 成功開啟."
                    + ">狀態:" + this.readyState
                    + ">版本:" + db.version
                    + "<br>";
                $('div').html(str);
            };
            req.onerror = function(evt){
                $('div').html("無法連結資料庫!<br>" + evt.target.errorCode);
            }
            //處理onupgradeneeded事件(若無資料庫,就會執行onupgradeneeded事件)
            req.onupgradeneeded = function(event){                
                var objectStore = event.target.result.createObjectStore("customer",{keyPath:"user_id"});
                objectStore.createIndex("name","name",{unique:false});
            };
            $("#delbtn").click(function(){
                //??不能直接在$(function(){...})中,直接用db.transaction建立transaction                
                //一定要設定在button的click事件中,db.transaction使用才不會出現錯誤:Uncaught TypeError: Cannot Read Property "transaction"
                delete_objectstore("A0001");
            });             

            function delete_objectstore(user_id){
                //開啟交易
                var transaction = db.transaction("customer","readwrite");
                transaction.oncomplete = function(event){
                    str+="交易成功<br>";
                    $("div").html(str);
                };
                transaction.onerror = function(event){$("div").html("交易失敗");};

                //取得objectStore
                store = transaction.objectStore("customer");

                transaction.oncomplete = function(event){
                    str+="交易成功<br>";
                    $("div").html(str);
                };
                transaction.onerror = function(event){$("div").html("交易失敗");};

                //4.刪除資料
                var req = store.delete(user_id);
                req.onsuccess = function(e){
                    str += "資料刪除成功." + "A0001已被刪除<br>";
                    $('div').html(str);
                };
                req.onerror = function(e){
                    $('div').html("資料刪除失敗.");
                };
            }
        });
    </script>
</head>
<body>
    <div id="message"></div>
    <button id="delbtn">刪除A0001</button>
</body>
</html>
feeer2380 iT邦新手 5 級 ‧ 2021-03-26 11:47:28 檢舉
indexedDB是非同步
js在處理非同步的事件時,似乎會放在最後處理
所以當你把transaction直接放在宣告後面時
db應該還沒產生出來
你可以把transaction的動作全塞進req.onsuccess裡面試試看
O口O iT邦新手 5 級 ‧ 2021-03-27 17:31:49 檢舉
這樣就可以了,只是不大清楚確定的原理.
感謝feer2380的回答

尚未有邦友回答

立即登入回答