【发布时间】:2019-03-24 05:20:16
【问题描述】:
我必须在这里遗漏一些非常基本的东西,如果您能提供任何指导,我将不胜感激。谢谢。
当注释掉的 try-catch 与 catch 中的 abort 事务处于活动状态时,我认为以下代码正在工作。中止事务在每个先前成功的 req 上触发了 req.onerror,而每个成功的 req 又触发了 transaction.onerror 和太多递归错误。我解决了这个问题,并且知道的不多,认为一切正常,以至于个别请求错误触发 req.onerror 并回滚事务。然而,似乎只有在 catch 中的 abort 语句才会触发它。我通过发送无法解析为 JSON 字符串的错误数据来测试错误场景。
但是,现在,我在不需要 try-catch 和随后的中止的场景中使用相同的代码,我无法触发 req.onerror 并且不明白为什么。
传递给 DB_pop 的参数 o 是一个对象,其中包含对象存储的名称、一个数据对象数组和一个用于“add”或“put”的字符串。我故意传递一个好的数据对象和一个带有空键的数据对象,如下面的第一个代码语句所示。好的会写,坏的不会。 req.onerror 和 transaction.onerror 不会触发。只有 transaction.oncomplete 触发。此外,只有一个 req.onsuccess 触发。我得出结论是因为控制台日志中写入的内容。
连接到调用 DB_pop 函数的 Promise 的 then 语句运行拒绝函数。回滚函数运行,关闭then 清理变量以防止内存泄漏运行。我也不明白这一点,因为如果仅触发了 transaction.oncomplete,它应该解决而不是拒绝。
为什么不会为第二个数据对象触发 req.onerror 并导致事务回滚并删除写入的第一个数据对象?
我尝试将 req 设为一个数组,并删除 d 循环并使用 null 键传递单个数据对象,并且不会触发 onerror 事件。
我确实注意到,如果在现有密钥上将错误作为add 编造到数据库中,那么所有错误事件都会触发,甚至会触发数据库打开/创建中设置的一般错误事件。 put 中的空键似乎不会按预期触发错误并回滚。
p = DB_pop( { 'os' : 'topics', 'data' : [ { 'key' : 0, 'gap' : T.gap, 'max' : T.max, 'selKey' : key }, { 'key' : null, 'title' : t, 'created' : d, 'edited' : d } ], 'op' : 'put' } );
p.then( () => { T.title = t; }, rollback ).then( () => { evt = key = t = T = d = p = m = null; console.log('cleaned up'); } );
function DB_pop( o ) // ( os, data, op )
{
return new Promise( ( resolve, reject ) =>
{
if ( !DB_open.base ) reject( 'Failed to populate database ' + DB_open.title + ' because the database is closed or does not exist.' );
let t = DB_open.base.transaction( [ o.os ], 'readwrite' ),
s = t.objectStore( o.os ),
req, d;
DB_pop.error = false;
function free_RAM()
{
t = s = req = d = null;
} // close free_RAM
t.oncomplete = ( e ) =>
{
console.log('trans complete');
resolve();
free_RAM();
e = null;
}; // close t.oncomplete
t.onerror = ( e ) =>
{
//e.stopPropagation(); // Stop propagation up to the database error level in the database open block.
DB_pop.error = true;
reject(e);
console.log( 'Transaction error : ' + e.target.error );
free_RAM();
e = null;
}; // close t.onerror
t.onabort = ( e ) =>
{
console.log( 'Transaction aborted : ' + e.target.error );
free_RAM();
e = null;
}; // close t.onabort
for ( d of o.data )
{
// try
// { let q = JSON.parse( { 'x' : d, 'y' : 3 } ); }
// catch(e)
// { t.abort(); error = true; break; } //?????????? Test what takes place if the try fails.
req = s[ o.op ]( d ); // o.op is either 'add' or 'put'.
req.k = d.key;
req.n = d.nbr;
req.onsuccess = function( e )
{
if ( !DB_pop.error )
{
console.log( 'Success at k = ' + this.k + '.' );
}; // end if
}; // close req.onsuccess
req.onerror = function( e )
{
/*
When a transaction is rolled back/aborted, every request's error event is fired and propagates up to transaction.onerror and causes a "too much recursion" error.
Thus, let it propagate once and, within transaction.onerror, set error to true.
*/
console.log( 'Request.onerror fired. Error = ' + e.target.error + ' k = ' + this.k + ', n = ' + this.n );
if ( DB_pop.error )
{
e.stopPropagation();
console.log( 'Stopping propagation' );
}; // end if
}; // close req.onerror
}; // next d
}); // close promise
} // close DB_pop
【问题讨论】:
-
也许尝试在您的拒绝回调中打印原因:
p.then(() => { /* fulfilled */ }, (reason) -> console.log(reason))。 executor 函数中的异常会出现在这里。 -
感谢您的回复。它确实打印了一个原因,即“DataError:提供给操作的数据不符合要求”。我认为这是因为密钥为空。问题是,即使有这个错误响应,事务在任何级别都没有事件错误的情况下完成,但是当它应该回滚时它只是部分完成。它似乎适用于对现有键的添加尝试,因为我后来添加到我的问题中,但在放置尝试中不是空键。
标签: indexeddb