未捕获的TypeError:无法使用indexeddb读取null的属性“transaction” [英] Uncaught TypeError: Cannot read property 'transaction' of null with an indexeddb

查看:125
本文介绍了未捕获的TypeError:无法使用indexeddb读取null的属性“transaction”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到错误'未捕获的TypeError:在此段代码中无法读取null'
的属性'transaction'

I am getting an error 'Uncaught TypeError: Cannot read property 'transaction' of null ' when in this section of code

  remoteDB.indexedDB.addAdmins = function() {
           var db = remoteDB.indexedDB.db;
           var trans = db.transaction("students", "readwrite");
           var request = trans.objectStore("administrators");
           /*
          this section edited out since the failure is on line 3
           */
        request.onsuccess = function(e) {

                console.log("success Adding: ", e);
            };


           request.onerror = function(e) {
             console.log(e.value);
           }; 
         };


推荐答案

remoteDB.indexedDB.db为空。这似乎是一个全局变量引用。为了创建事务,必须定义变量,而不是null,并且打开。

remoteDB.indexedDB.db is null. This appears to be a global variable reference. In order to create a transaction, the variable must be defined, not null, and open.

indexedDB是异步的。无法保证当您打开与indexedDB的连接并在全局变量中保存连接句柄时,该变量仍然定义,而不是null,并在稍后的时间点从另一个异步函数的上下文中打开。

indexedDB is async. There is no guarantee that when you open a connection to indexedDB and save the handle of the connection in a global variable that the variable is still defined, not null, and open at a later point in time from within the context of another asynchronous function.

如果您立即开启交易,它有时会起作用。有时数据库连接仍然存在。但它不能保证。如果数据库连接上没有打开的事务,那么浏览器将在那之后的某个时刻关闭连接。

It will work sometimes, if you immediately open a transaction. Sometimes the db connection persists. But it is not guaranteed. If there are no open transactions on a database connection then the browser will close the connection at some point there after.

参见

  • Why is db.transaction not working with indexeddb?
  • Is it bad to open several database connections in indexedDB?
  • Why is onupgradeneeded never called in this code?
  • etc.

这个错误部分通常是因为程序员不熟悉异步javascript。这不是批评,它似乎只是一种常见的模式。为避免将来出现错误,我建议花些时间学习异步javascript。

This error occurs in part usually because of a programmer's lack of familiarity with asynchronous javascript. This is not a criticism, it just seems to be a common pattern. To avoid errors in the future, I suggest spending some time learning about asynchronous javascript.

例如,了解以下内容的工作原理(或者说为什么它不能按预期工作)在尝试使用indexedDB之前:

For example, understand how the following works (or rather why it does not work as expected) before trying to use indexedDB:

var db;
function setDB() {
  db = 123;
}
setTimeout(setDB, 10);
console.log('Got a db variable! %s', db);

要真正做到这一点,对于stackoverflow和富有洞察力的文章和指南上的数千个其他问题来说,公正将是多余的在网上,但这是一个极端的速成课程。 indexedDB.open是一个异步(异步)函数。形容词异步意味着很多。异步函数的行为与同步函数的行为完全不同。新的javascript程序员通常只学习同步编程。所以很自然地你不明白为什么在同步代码中调用异步函数不起作用。同步示例:

To really do this justice would be redundant with the thousands of other questions on stackoverflow and insightful articles and guides on the web, but here is an extreme crash course. indexedDB.open is an asynchronous (async) function. The adjective asynchronous means alot. An async function behaves extremely differently than a synchronous function. New javascript programmers generally only learn to program synchronously. So naturally you don't get why calling an async function in your sync code does not work. Sync example:

var a = 1;
var b = 2;
function sum(arg1, arg2) { return arg1 + arg2 }
var abSum = sum(a,b);
console.log('The sum of a + b is %s', abSum);

你知道在a = 1之后执行b = 2,并且sum = a + b是在b之后执行。这些语句按顺序,按行,按顺序依次执行,按照您编写的顺序执行。你知道,如果你试图将第4行放在第1行之前,它将无法工作,因为a和b还没有值。在同步代码中,您知道函数sum返回一个值。它会立即返回。因此,您知道abSum会立即从调用sum(a,b)中分配返回值。

You know that b=2 is executed after a=1, and that sum=a+b is executed after b. The statements are executed in order, in line, in serial, one after the other, in the order you wrote them. You know that if you tried to put line 4 before line 1 above that it would not work because a and b do not yet have values. In synchronous code, you know that the function sum returns a value. It returns it immediately. So you know that abSum is immediately assigned the return value from calling sum(a,b).

异步代码的工作方式截然不同。通常,异步函数不会返回所需的值。通常将函数(称为回调函数)传递给函数。异步函数只保证它会在稍后调用回调。它没有返回要使用的东西。

Async code works extremely differently. In general, async functions do not return the value you want. Usually you pass in a function (called a callback function) to the function. An async function only sort of guarantees it will call the callback some time later. It does not return something to use.

var a = 1;
var b = 2;
function asyncSum(arg1,arg2,calledWhenFinished) {
  var sum = arg1+arg2;
  calledWhenFinished(sum);
  return 'asyncSumFinished and called the callback';
}

// The following DOES NOT work as expected
var theResultOfSum = asyncSum(a,b, function(sum) {
 console.log('finished. The um is %s', theResultOfSum);
});

// The following DOES work as expected
asyncSum(a,b, function(sum) {
 console.log('The sum is %s', sum);
});

请注意,在工作示例中,我不关心asyncSum返回的内容。毕竟,它不会返回总和,它只返回一个字符串,表示它已完成。现在让我们做一些更真实的异步。

Notice that here in the working example, I don't care about what asyncSum returns. After all, it does not return the sum, it just returns a string saying it finished. Now let's do something that is more genuinely async.

function moreGenuineAsyncSum(a,b, callback) {
  setTimeout(function() {
    var sum = a + b;
    console.log('The sum is %s', sum);
    callback(sum);
  }, 100);
  console.log('Requested the sum to be calculated');
  return 'Hey, I scheduled the callback function to execute in 100ms';
}

这里我真的不关心moreGenuineAsyncSum的返回值。事实上,它毫无价值。这只是一个字符串。还要注意首先执行哪个console.log调用。后一行在前一行之前执行。故障。不按照它的编写顺序。这是为什么?因为这是异步函数所做的事情,所以它们会在稍后的某个时间点执行某些操作。

Here I really don't care about the return value of moreGenuineAsyncSum. In fact, it is worthless. It is just a string that says something. Also notice which console.log call gets executed first. The later line gets executed before the earlier line. Out of order. Out of the order in which it was written. Why is that? Because that is what async functions do, they do something at a later point in time.

indexedDB.open是一个异步函数。它返回一个IDBOpenRequest对象,它是一种Request对象。大多数indexedDB函数都是异步并返回Request对象。请求对象没有值。他们将回调作为属性。因此:

indexedDB.open is an async function. It returns a IDBOpenRequest object, which is a type of Request object. Most indexedDB functions are async and return Request objects. Request objects do NOT have values. They have callbacks as properties. Therefore:

var dbRequest = indexedDB.open('mydb',1);
dbRequest.onsuccess = function(event) {
  // This gets called later. The following are all viable ways to get the IDBDatabase
  // object INSIDE THE BLOCK OF THIS FUNCTION ONLY. Any one of the following 3 lines
  // works exactly the same way.
  var db = this.result;
  var db = dbRequest.result;
  var db = event.target.result;

  console.log('Got a db connection! It is %s', db);

  // Now, INSIDE THE BLOCK OF THIS FUNCTION ONLY, do something:
  var myTransaction = db.transaction('myObjectStore','readwrite');
  var myObjectStore = myTransaction.objectStore('myObjectStore');

  // etc.
};

在我写完整本书之前总结一下,重点是上面的INSIDE THE BLOCK评论。在块内部,'db'变量保证在那里,并且是开放的,并且被定义,而不是null。在块之外,db变量不存在。

To sum this up before I write an entire book, the emphasis is on the INSIDE THE BLOCK comments above. Inside the block, the 'db' variable is guaranteed to be there, and be open, and be defined, and not null. Outside the block, the db variable does not exist.

所以你可能会说,这使得使用indexedDB非常烦人。你是对的,这很烦人。为了减少对你的烦恼,你可以了解承诺。或者你可以像函数一样编写回调函数。或者你可以使用处理回调地狱的无数设计模式之一。有许多。一种是使用像EventTarget这样的模式及其与DOM的关系。

So you might be saying, that makes it pretty damn annoying to use indexedDB. You are right, it is annoying. To make it less annoying to you, you can learn about promises. Or you can write callback like functions. Or you can use one of the myriad of design patterns that deal with callback hell. There are many. One is just using a pattern like EventTarget and its relation to the DOM.

这篇关于未捕获的TypeError:无法使用indexeddb读取null的属性“transaction”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆