1

iOS6 のリリース以来、私の Web アプリは一連のバグに遭遇しました。最悪の 1 つは、websql トランザクションがキューに入れられていることをほぼ 100% 確信していることです。モバイルサファリ(ipad)でアプリを最初にロードすると、トランザクションは正常に機能します。次に、Safari を閉じて再度開くと、トランザクションがキューに入れられ、実行されないように見えます。

開発ツールを開いて単純なを実行するalertと、メソッドが起動し、リロードを押すだけでトランザクションが正常に動作するか、db トランザクションの実行を 1 秒または何か遅らせると、同様に正常に動作します。

トランザクションを実行するために setTimeout を実行したくありません。

これは、サファリが実装してからキャッシングの問題ですか?

これを修正する方法について何か良いアイデアがある場合は、以下に回答してください。

前もって感謝します。

4

2 に答える 2

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);
  }

};
于 2012-09-27T02:47:47.120 に答える
0

結局のところ、websql の前に Facebook を初期化すると問題が発生していました。FB をコメントアウトした後、アプリは適切に動作したため、setTimeout も問題を解決しました。fb api の準備ができました。実行スレッドがどのようにブロックされるかはわかりません。

したがって、FB を使用していて websql トランザクションを実行しようとしている人は、FB を遅らせてください。

ただし、websql はサファリのロードでまだ少し遅く実行されています...

于 2012-09-27T19:07:43.330 に答える