2016-05-10 3 views
2

私はJSをよく理解していますが、最終的にはまだ学習しています。私はIndexedDBにPHP/mySQLプロジェクトを再作成しようとしています。なぜここでエラーが発生しているのか理解できません。グローバル変数は最初の関数のみにアクセスできますか?

IndexedDB接続は正常に動作します。最初の関数(createItem)は正常に機能しますが、2番目の関数(getItems)は "db"変数が未定義であると主張するエラーを返しています。これはグローバル変数であり、関数のスコープでアクセス可能でなければならず、createItem関数はそれを使用しても問題ありません。誰も私がここで逃したものを見て助けることができます。

// GLOBAL DB VAR 
var db; 
// WAIT FOR DOM 
document.addEventListener("DOMContentLoaded", function(){ 
    // IF INDEXED DB CAPABLE 
    if("indexedDB" in window) { 
     // OPEN DB 
     var openRequest = indexedDB.open("newTabTest",1); 
     // CREATE NEW/UPDATE 
     openRequest.onupgradeneeded = function(e) { 
      // Notify user here: creating database (first time use) 
      var thisDB = e.target.result; 
      // Create "items" table if it doesn't already exist 
      if(!thisDB.objectStoreNames.contains("items")) { 
       var store = thisDB.createObjectStore("items", {keyPath: "id", autoIncrement: true}); 
       store.createIndex("name","name", {unique:true}); 
       store.createIndex("folder","folder", {unique:false}); 
       store.createIndex("dial","dial", {unique:false}); 
      } 
     } 
     openRequest.onsuccess = function(e) { 
      // Success- set db to target result. 
      db = e.target.result; 
     } 
     openRequest.onerror = function(e) { 
      // DB ERROR :-(
     } 
    } 
},false); 

// CREATE ITEM FUNCTION 
function createItem(n,u,f,c) { 
    var transaction = db.transaction(["items"],"readwrite"); 
    var store = transaction.objectStore("items"); 
    var item = { 
     name: n, 
     url: u, 
     folder: f, 
     colour: c, 
     dial: 0, 
     order: 100 
    } 
    var request = store.add(item); 
    request.onerror = function(e) { 
     console.log("An error occured."); 
    } 
    request.onsuccess = function(e) { 
     console.log("Successfully added.") 
    } 
}; 

// GET ITEM(S) FUNCTION 
// Specify index and key value OR omit for all 
function getItems(callback, ind, key) { 
    var transaction = db.transaction(["items"],"readonly"); 
    var store = transaction.objectStore("items"); 
    var response = []; 

    // If args are omitted - grab all items 
    if(!ind | !key) { 
     var cursor = store.openCursor(); 
     cursor.onsuccess = function(e) { 
      var res = e.target.result; 
      if(res) { 
       var r = { 
        "name": res.value['name'], 
        "url": res.value['url'], 
        "folder": res.value['folder'], 
        "colour": res.value['colour'], 
        "dial": res.value['dial'], 
        "order": res.value['order'] 
       }; 
       response.push(r); 
       res.continue(); 
      } 
     } 
     cursor.oncomplete = function() { 
      callback(response); 
     } 
    } else { 
     // If both args are specified query specified index 
     store = store.index(ind); 
     var range = IDBKeyRange.bound(key, key); 
     store.openCursor(range).onsuccess = function(e) { 
      var res = e.target.result; 
      if(res) { 
       var r = { 
        "name": res.value['name'], 
        "url": res.value['url'], 
        "folder": res.value['folder'], 
        "colour": res.value['colour'], 
        "dial": res.value['dial'], 
        "order": res.value['order'] 
       }; 
       response.push(r); 
       res.continue(); 
      } 
     } 
     cursor.oncomplete = function() { 
      callback(response); 
     } 
    } 
}; 
+4

私は「あなたを考えます2番目の関数が変数にアクセスしていますが、その* value *は 'undefined 'です。あなたはどこから関数を呼び出しますか? 'db = ...'を設定する非同期コードが実行される前に呼び出すと思います。 – nnnnnn

+0

上記のスクリプトの下にgetItemsを呼び出すことを試みましたが、関数を呼び出さなくても、その行に定義されていないdbについてコンソールにエラーが表示されます。 –

+0

Ahhh。あなたはそこに何かあるかもしれません!私は本当にこの非同期ビジネスの周りに頭を浮かべる必要があります。どうすればこの作業を確実に行うことができますか?おそらく、dbedcompleteによって呼び出される関数の中に、db依存の動作を張るのでしょうか? –

答えて

2

あなたはコメントで考え出してきたように、あなたはsuccessハンドラから呼び出される関数の内部でDB-依存アクションを固執する必要があります。

このコールバックベースのプログラミングはすばやく痛みを伴い、そのための一般的な解決方法はpromisesです。

しかし、約束事でIndexedDBを動作させることはまだ進行中です(興味があればhttps://github.com/inexorabletash/indexeddb-promisesを参照してください)。

あなたの目標は何かを成し遂げることです(と裸のIndexedDB APIを学ぶことではない)場合は、おそらくあなたはwrapper library for IndexedDBを見つけるほうが良いと思います私は真剣に取り組んでみましたいませんでしたので、(、ただし1をお勧めすることはできませんIDBはまだ)。

0

あなたの例にあるように、 'db'のような変数の使用をお勧めしません。非同期のJavascriptを読んだり書いたりするのが初めての方は、あなた自身に苦痛を与えることになります。それを行うより良い方法があります。それは説明するいくつかのページを取り、StackOverflowの上の他の多くの質問で説明されているので、代わりに、非常に簡単に、以下のような何かをするようにコードを書き換える考えてみます。

function createItem(db, ...) { 
    var tx = db.transaction(...); 
    // ... 
} 

function openIndexedDBThenCreateItem(...) { 
    var openRequest = indexedDB.open(...); 
    openRequest.onsuccess = function(event) { 
    var db = event.target.result; 
    createItem(db, ...); 
    }; 
} 

function getItems(db, callback, ...) { 
    var tx = db.transaction(...); 
    var items = []; 
    tx.oncomplete = function(event) { 
    callback(items); 
    }; 

    // ... 
    var request = store.openCursor(...); 
    request.onsuccess = function(event) { 
    var request = event.target; 
    var cursor = event.target.result; 
    if(cursor) { 
     var item = cursor.value; 
     items.push(item); 
     cursor.continue(); 
    } 
    }; 
} 

function openIndexedDBThenGetItems(db, callback, ...) { 
    var openRequest = indexedDB.open(...); 
    openRequest.onsuccess = function(event) { 
    var db = event.target.result; 
    getItems(db, callback, ...); 
    }; 
} 

また、あなたは待つ必要はありませんDOMContentLoadedを実行してindexedDBの使用を開始します。それはすぐに利用可能です。その後、

function openIndexedDB(callback) { 
    var openRequest = indexedDB.open(...); 
    openRequest.onerror = callback; 
    openRequest.onsuccess = callback; 
} 

そして、このような例を書き換える:

あなたは上記のコードを取得した場合、その後、あなたは、単純なヘルパー関数を追加することのさらなる向上を考慮することができる

function openIndexedDBThenCreateItem(...) { 
    openIndexedDB(function onOpen(event) { 

    if(event.type !== 'success') { 
     console.error(event); 
    } else { 
     var db = event.target.result; 
     createItem(db, ...); 
    } 
    }); 
} 

function openIndexedDBThenGetItems(...) { 
    openIndexedDB(function onOpen(event) { 
    if(event.type !== 'success') { 
     console.error(event); 
    } else { 
     var db = event.target.result; 
     getItems(db, ...); 
    } 
    }); 
} 
関連する問題