2012-09-26 2 views
1

iOS6이 출시 된 이래로 내 웹 응용 프로그램은 일련의 버그에 직면했습니다. 최악의 상황 중 하나는 거의 100 % 확실합니다. 대기중인 websql 트랜잭션입니다. 모바일 사파리 (ipad)에서 앱을 처음로드하면 트랜잭션이 정상적으로 작동합니다. 그런 다음 사파리를 닫고 다시 열면 트랜잭션이 대기열에있는 것처럼 보이고 결코 실행되지 않습니다.Websql queued execution - iOS6 Mobile Safari

dev 도구를 열고 간단한 alert을 실행하면 메소드가 실행됩니다. 다시로드해도 작업이 제대로 작동하거나 DB 트랜잭션이 1 초 정도 지연되거나 정상적으로 작동하면 지연됩니다. 게다가.

트랜잭션을 실행하기 위해 setTimeout을 실행하지 않으려합니다.

Safari가 구현 된 후 캐싱 문제가 있습니까?

누구든지이 문제를 해결하는 방법에 대해 좋은 아이디어가 있다면 아래 답변하십시오.

미리 감사드립니다.

답변

0

이 websql이 문제의 원인이되기 전에 페이스 북을 초기화 밝혀 지. FB를 주석 처리 한 후 앱이 제대로 작동했기 때문에 setTimeout이 문제를 해결 한 이유입니다. fb api가 준비되었습니다. 실행 스레드가 차단되는 방식, 잘 모르겠습니다.

그래서 FB를 사용하고 websql 트랜잭션을 실행하려고하면 FB가 지연됩니다!

비록 websql이 사파리로드에서 약간 느리게 실행 중입니다 ...

+0

전자 메일 대화 상자가 열려 있고 websql 트랜잭션이 실행을 시도 할 때이 문제가 다시 발생했습니다. 실행되지 않습니다! – Trevor

0

버그 일 수 있습니다. 불필요하게 일련의 트랜잭션을 사용 중일 수 있습니다. 트랜잭션 당 여러 개의 요청을 사용할 수 있습니다. onsuccess 콜백을 사용하면 트랜잭션을 다시 사용할 수 있습니다. 그것은 작동해야합니다. 동시에 트랜잭션 당 요청 수를 제한하십시오. setTimeout은 절대 필요하지 않습니다. 여기

이 하나의 트랜잭션이 트랜잭션 큐에 관해서는 여러 개체

/** 
* @param {goog.async.Deferred} df 
* @param {string} store_name table name. 
* @param {!Array.<!Object>} objects object to put. 
* @param {!Array.<(Array|string|number)>=} opt_keys 
*/ 
ydn.db.req.WebSql.prototype.putObjects = function (df, store_name, objects, opt_keys) { 

    var table = this.schema.getStore(store_name); 
    if (!table) { 
    throw new ydn.db.NotFoundError(store_name); 
    } 

    var me = this; 
    var result_keys = []; 
    var result_count = 0; 

    /** 
    * Put and item at i. This ydn.db.core.Storage will invoke callback to df if all objects 
    * have been put, otherwise recursive call to itself at next i+1 item. 
    * @param {number} i 
    * @param {SQLTransaction} tx 
    */ 
    var put = function (i, tx) { 

    // todo: handle undefined or null object 

    var out; 
    if (goog.isDef(opt_keys)) { 
     out = table.getIndexedValues(objects[i], opt_keys[i]); 
    } else { 
     out = table.getIndexedValues(objects[i]); 
    } 
    //console.log([obj, JSON.stringify(obj)]); 

    var sql = 'INSERT OR REPLACE INTO ' + table.getQuotedName() + 
     ' (' + out.columns.join(', ') + ') ' + 
     'VALUES (' + out.slots.join(', ') + ');'; 

    /** 
    * @param {SQLTransaction} transaction transaction. 
    * @param {SQLResultSet} results results. 
    */ 
    var success_callback = function (transaction, results) { 
     result_count++; 
     result_keys[i] = goog.isDef(out.key) ? out.key : results.insertId; 
     if (result_count == objects.length) { 
     df.callback(result_keys); 
     } else { 
     var next = i + ydn.db.req.WebSql.RW_REQ_PER_TX; 
     if (next < objects.length) { 
      put(next, transaction); 
     } 
     } 
    }; 

    /** 
    * @param {SQLTransaction} tr transaction. 
    * @param {SQLError} error error. 
    */ 
    var error_callback = function (tr, error) { 
     if (ydn.db.req.WebSql.DEBUG) { 
     window.console.log([sql, out, tr, error]); 
     } 
     df.errback(error); 
     return true; // roll back 
    }; 

    //console.log([sql, out.values]); 
    tx.executeSql(sql, out.values, success_callback, error_callback); 
    }; 

    if (objects.length > 0) { 
    // send parallel requests 
    for (var i = 0; i < ydn.db.req.WebSql.RW_REQ_PER_TX && i < objects.length; i++) { 
     put(i, this.getTx()); 
    } 
    } else { 
    df.callback([]); 
    } 
}; 

를 삽입하는 데 사용되는 방법, 응용 프로그램보다는 안정성에 대한 SQLite는에 의해 처리하는 것이 좋습니다. 기본적으로 새로운 거래를 시작하기 전에 거래 complete 이벤트를 볼 수 있습니다. 또한 제어가 가능한 한 여러 트랜잭션을 실행하는 것이 좋습니다. 통제 불능 상태가되면 루프를 통해 트랜잭션이 열리게됩니다. 일반적으로 나는 단지 몇 가지 거래를 열 것이다. 여기

는 트랜잭션이 대기하는 방법입니다

/** 
* Create a new isolated transaction. After creating a transaction, use 
* {@link #getTx} to received an active transaction. If transaction is not 
* active, it return null. In this case a new transaction must re-create. 
* @export 
* @param {Function} trFn function that invoke in the transaction. 
* @param {!Array.<string>} store_names list of keys or 
* store name involved in the transaction. 
* @param {ydn.db.TransactionMode=} opt_mode mode, default to 'readonly'. 
* @param {function(ydn.db.TransactionEventTypes, *)=} oncompleted 
* @param {...} opt_args 
* @override 
*/ 
ydn.db.tr.TxStorage.prototype.transaction = function (trFn, store_names, opt_mode, oncompleted, opt_args) { 

    //console.log('tr starting ' + trFn.name); 
    var scope_name = trFn.name || ''; 

    var names = store_names; 
    if (goog.isString(store_names)) { 
    names = [store_names]; 
    } else if (!goog.isArray(store_names) || 
    (store_names.length > 0 && !goog.isString(store_names[0]))) { 
    throw new ydn.error.ArgumentException("storeNames"); 
    } 
    var mode = goog.isDef(opt_mode) ? opt_mode : ydn.db.TransactionMode.READ_ONLY; 
    var outFn = trFn; 
    if (arguments.length > 4) { // handle optional parameters 
    var args = Array.prototype.slice.call(arguments, 4); 
    outFn = function() { 
     // Prepend the bound arguments to the current arguments. 
     var newArgs = Array.prototype.slice.call(arguments); 
     //newArgs.unshift.apply(newArgs, args); // pre-apply 
     newArgs = newArgs.concat(args); // post-apply 
     return trFn.apply(this, newArgs); 
    } 
    } 
    outFn.name = scope_name; 

    var me = this; 

    if (this.mu_tx_.isActive()) { 
    //console.log(this + ' active') 
    this.pushTxQueue(outFn, store_names, mode, oncompleted); 
    } else { 
    //console.log(this + ' not active') 
    var transaction_process = function (tx) { 

     me.mu_tx_.up(tx, scope_name); 

     // now execute transaction process 
     outFn(me); 

     me.mu_tx_.out(); // flag transaction callback scope is over. 
     // transaction is still active and use in followup request handlers 
    }; 

    var completed_handler = function (type, event) { 
     me.mu_tx_.down(type, event); 
     /** 
     * @preserve_try 
     */ 
     try { 
     if (goog.isFunction(oncompleted)) { 
      oncompleted(type, event); 
     } 
     } catch (e) { 
     // swallow error. document it publicly. 
     // this is necessary to continue transaction queue 
     if (goog.DEBUG) { 
      throw e; 
     } 
     } finally { 
     me.popTxQueue_(); 
     } 
    }; 

    if (ydn.db.tr.TxStorage.DEBUG) { 
     window.console.log(this + ' transaction ' + mode + ' open for ' + JSON.stringify(names) + ' in ' + scope_name); 
    } 
    this.storage_.newTransaction(transaction_process, names, mode, completed_handler); 
    } 

}; 
+0

답장을 보내 주셔서 감사합니다. 여러 요청을 실행하기 위해 단일 트랜잭션을 사용하고 있습니다. 내 질문에 명시된 바와 같이,이 문제는 iOS6 때까지 도입되지 않았고 트랜잭션 호출을 지연 시키거나 페이지를 다시로드하면 정상적으로 작동합니다. 닫힌 사파리에서 페이지를로드하는 경우에만 발생합니다. – Trevor

+0

나는 본다. 제 생각에는 iOS6이 요청을 강화했습니다. 다른 이유가있을 수 있습니다. 몇 가지 소스 코드가 문제를 파악하는 데 도움이 될 수 있습니다. –