IndexedDB事务错误冒泡到打开请求的db.onerror事件,但显示未捕获的异常错误

时间:2019-01-25 23:30:41

标签: javascript event-handling indexeddb

indexedDB.open请求的成功事件中,我有一个db.onerror事件处理程序,如“处理错误”部分中标题为Using IndexedDB:Opening a Database的MDN文档中所示。

在测试事务和请求错误时,我注意到即使在"Uncaught exception : undefined"处理程序中有停止传播语句,当事务出错时,在控制台中也会记录transaction.onerror。除非在transaction.onerror处理程序中没有停止传播语句,而在db.onerror处理程序中没有警告语句,否则不会给出脚本行号。然后,在控制台日志中返回警报语句的行号以及未捕获的异常消息。

请告诉我这是什么意思,如果这表明需要改进编码?谢谢。

除非我有误解,否则this问题似乎表明,transaction.onerror事件不应在打开的请求中冒泡到db.onerror。请解释。

谢谢。

添加 在下面添加了两个代码块。一个打开数据库,另一个是写入数据库对象存储的事务。如果事务失败,则带有open函数的req.onsuccess事件的transaction.onerror事件会冒泡到db.onerror事件。无论是否防止这种情况,仍然存在如上所述的未捕获异常错误。

请注意,存在pop_db函数中有关错误的异常代码,因为如果try / catch失败并且手动中止了事务,则所有req.onerror事件都会为事务中的每个请求触发,这导致一个“递归过多”错误,因为每个req.onerror事件都触发了transaction.onerror事件。

谢谢。

  DB.open_db = ( o ) =>
    { 
      return new Promise( ( resolve, reject ) =>
        {
          // Request to open database.
          let old_v,
              req = o.version ? indexedDB.open( DB.name, o.version ) : indexedDB.open( DB.name );

          req.onerror = ( event ) => { }; // close onerror

          req.onsuccess = ( event ) =>
            { 
               DB.base = req.result;
               let db = DB.base;

               db.onerror = ( event ) =>
                 {
                   /*
                     Generic error handler for all errors targeted at this database's requests.
                     Transaction.onerror events bubble here if propagation not stopped.
                   */ 

                    alert( 'Database error: ' + event.target.error + '.' ); 
                    console.log( 'db.onerror event => Database error: ' + event.target.error + '.' );
                 }; // close onerror

               resolve( ' ... ' );

            }; // close onsuccess

          req.onupgradeneeded = ( event ) => 
            {  
               // Save the IDBDatabase interface. 
               DB.base = event.target.result;
               let db = DB.base;
               /* 
                 Is a db.onerror needed, here, as seen in some of the MDN working examples? 
                 It appears that:
                   1. An error within onupgradeneeded triggers the req.onerror event.
                   2  A db.onerror function within onupgradeneeded doesn't fire at all but goes straight to req.onerror.
               */

               old_v = event.oldVersion;
               if ( old_v < 1 )
                 // Brand new database needs all objectStores created.
                 {
                    db.createObjectStore( "data" ); 
                 }
               else 
                 {
                   // Upgrade to existing database required/requested.                                     
                 }; //  end if old_v
            }; // close onupgradeneeded

        } ); // close new promise

      }; // close DB.open

      DB.pop_db = ( o ) =>  // ( os, data, op )

        { 
          /* 
             A note about transaction and request events. Every request.onerror event handler, in turn, fires the transaction.onerror event handler.
             This was causing "too much recursion" errors. Coded it this way in order to track the key and question numbers to test against other data.
             Coded such that the first request.onerror bubbles and then the first statement of the transaction.onerror event handler sets the condition that stops
             the propogation of all further request.onerror events that subsequently fire as a result of aborting the transaction due to bad data. 
             Therefore, the transaction.onerror event is fired only once. 
             If an individual request errors the transaction will complete but the program won't continue. So, need req.onerror.
          */

          return new Promise( ( resolve, reject ) =>
            {
              let t = DB.base.transaction( [ o.os ], 'readwrite' ),
                  s = t.objectStore( o.os ),
                  req, d;

              DB.pop_db.error = false;

              t.oncomplete = ( e ) =>
                {
                  resolve();
                }; // close t.oncomplete

              t.onerror = ( e ) =>
                {
                  //e.stopPropagation(); // Stop propagation up to the database error level in the database open block.
                  DB.pop_db.error = true;
                  reject();
                }; // close t.onerror


              t.onabort = ( e ) =>
                {
                  console.log( 'Transaction aborted : ' + e.target.error );
                }; // close t.onabort

             for ( d of o.data )
               { 
                try
                 { ... }
                catch(e)
                 { t.abort(); break; }

                 req = s[ o.op ]( d );
                 req.k = d.key; 
                 req.n = d.nbr;

                 req.onsuccess = function( e )
                   {
                     if ( !DB.pop_db.error )
                       {
                         console.log( 'Success at k = ' + this.k + ', nbr = ' + this.n + '.' );
                       }; // 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_db.error )
                       {
                         e.stopPropagation();
                         console.log( 'Stopping propagation' );
                       }; // end if

                   }; // close req.onerror

               }; // next d

         }); //  close promise

     }; // close DB.pop_db

0 个答案:

没有答案
相关问题