Javascript 控制清理函数相对于indexedDB中异步请求的执行顺序?

Javascript 控制清理函数相对于indexedDB中异步请求的执行顺序?,javascript,asynchronous,settimeout,indexeddb,Javascript,Asynchronous,Settimeout,Indexeddb,在indexedDB数据库事务中,有多个add、get和put请求位于try catch中。即使用户在外部篡改数据,在试图保护程序不失败时也会出现一个问题,即当其中一个请求出错时,所有请求的错误事件都会被触发并冒泡到事务错误事件,因此transaction.onerror中的代码会多次运行。通过将布尔变量声明为false,然后在transaction.onerror中将其设置为true,并在每个请求.onerror函数中对其进行测试,如果为true,则执行evt.stopPropagation(

在indexedDB数据库事务中,有多个
add
get
put
请求位于
try catch
中。即使用户在外部篡改数据,在试图保护程序不失败时也会出现一个问题,即当其中一个请求出错时,所有请求的错误事件都会被触发并冒泡到事务错误事件,因此
transaction.onerror
中的代码会多次运行。通过将布尔变量声明为false,然后在
transaction.onerror
中将其设置为true,并在每个
请求.onerror
函数中对其进行测试,如果为true,则执行
evt.stopPropagation()

除了一个小问题外,这是可行的。为了防止内存泄漏的可能性,在
transaction.oncomplete
transaction.onerror
结束时,通过调用内部函数freeRAM(),将数据库函数中的所有变量设置为null。由于
transaction.onerror
函数可以在发出所有请求之前执行,因此freeRAM()函数可以将所有变量设置为null,从而导致其他本可以成功运行的请求失败,并且由于布尔变量也被清除,用于阻止后续请求错误冒泡到
transaction.onerror
的技术失败,因为该变量在该点为null

我的问题是,有没有一种方法可以在所有请求成功或出错后执行freeRAM()?freeRAM()上的
setTimeout
是否能确保在所有请求完成后它进入堆栈

在测试中,在执行freeRAM()之前,在
transaction.onerror
函数中放置一条提示数据库错误的警报消息,让请求有时间完成;但是我想要一个更好的方法。我知道我不能简单地将“error”和其他相关变量设置为null,但我想知道是否可以将freeRAM()的执行设置为始终在所有请求完成后执行

我尝试使用
setTimeout(free_RAM,0)
代替
alert
,它似乎可以工作,但我不确定它是否会在请求完成后始终执行freeRAM(),或者它是否只是用于我的测试。也许,在用户单击“确定”后执行freeRAM()的自定义消息就足够了,或者可以为
setTimeout
添加更多时间。这些是短事务,请求写入少量数据

代码如下。多谢各位

  error = false;
  T.onerror = ( v ) =>
    {
      v.stopPropagation(); // Stop propagation up to the database error level in the database open block.
      if ( !error ) 
        {
          error = true; 
          // Next two statements must execute only once.
          if ( m ) { Q.max = key - 1; } else { Q.gap.push(key); };
          if ( log ) undo_rollbackKey( qst_undo );
          alert( 'bad data' ); // If this is removed, program fails for bad data.
          free_RAM(); // Sets all variables, including 'error' to null;
        }; // end if
      v = null;
    }; // close T.onerror

    // Within the try-catch is code like this, involving 'error'.
    for ( i = 0; i < 9; i++ )
      { 
        req_a = q.add( { 'k' : k[i], 'c' : d, 'e' : d, 'E' : [] } );
        req_a.onerror = ( evt ) => { if ( error ) evt.stopPropagation(); }; 
      }; // next i

    req_b = q.add( { 'k' : [ key, 3, 0 ], 'g' : [], 'm' : 0, 'q' : [], 'N' : '', 'P' : '' } );
    req_b.onerror = ( evt ) => { if ( error ) evt.stopPropagation(); }; 
  let Q = { /* Object data */ },
      error = false;

  function freeRAM() { Q = error = null; }

  T.onerror = ( v ) => { v.stopPropagation(); };
  T.onabort = ( v ) =>
    {
      v.stopPropagation();
      if ( !error ) 
        {
          error = true; 
          // Next two statements must execute only once.
          if ( m ) { Q.max = key - 1; } else { Q.gap.push(key); };
          if ( log ) undo_rollbackKey( qst_undo );
          free_RAM(); // Sets all variables, including 'error' to null;
        }; // end if
      v = null;
    }; // close T.onerror

    try {
    for ( i = 0; i < 9; i++ )
      { q.add( { 'k' : k[i], 'c' : d, 'e' : d, 'E' : [] } ); }; 

    req = q.get( [ 0, 0, 0 ] );
    req.onsuccess = function() 
      {
        let r;
        try {
          if ( req.result )
           {
             r = req.result;
             /* Update r using variable set to null by freeRAM() */
             r.m = Q.max;
             q.put( r ); 
            }; // end if
          }
         catch(e) { if ( !error ) T.abort(); }
         finally { r = null; }             
      }; // close req.onsuccess
    } // close try
    catch { if ( !error ) T.abort(); }