2016-05-10 2 views
2

У меня есть хорошее понимание JS, но в конечном итоге я все еще участвую. Я пытаюсь воссоздать проект PHP/mySQL для IndexedDB и не могу понять, почему я вижу ошибку здесь.Глобальная переменная доступна только для первой функции?

Соединение IndexedDB работает должным образом. Первая функция (createItem) отлично работает, однако вторая функция (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

Я думаю, что вы» ll найти вторую функцию * является * доступ к переменной, но ее * значение * является 'undefined'. Откуда вы вызываете эту функцию? Я предполагаю, что вы вызываете его до запуска асинхронного кода, который устанавливает 'db = ...'. – nnnnnn

+0

Я пытался приклеить вызов getItems под сценарием выше, однако даже без вызова функции я получаю ошибку в консоли о том, что db не определено в этой строке. –

+0

Ahhh. Вы можете что-то там! Мне действительно нужно окунуться в этот асинхронный бизнес. Как я мог надежно выполнить эту работу? Возможно, придерживаться моих зависимых от db действий внутри функции, которая сама вызывается индексомddd oncomplete? –

ответ

2

Как вы уже выяснили, в комментариях, вы должны придерживаться ДБ-зависимых действий внутри функции вызывается из обработчика success.

Это программное обеспечение, основанное на обратном вызове, быстро становится больным, и для этого принято использовать promises.

Однако, работа IndexedDB с обещаниями все еще находится в процессе разработки (см. https://github.com/inexorabletash/indexeddb-promises, если вам интересно).

Если вы хотите что-то сделать (и не изучать голые API-интерфейсы IndexedDB), возможно, вам будет лучше найти wrapper library for IndexedDB (не могу порекомендовать, хотя, поскольку я не пробовал серьезно работать с 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, ...); 
    } 
    }); 
} 
Смежные вопросы