19

ほとんどの関数が非同期である JavaScript API を使用しています。API は、SQLite3 データベースを操作するための機能のサブセットへのバインドであるWebKit JavaScript データベース APIです。ブロックしないように非同期にするという設計上の決定を理解しており、応答性の高いユーザー インターフェイスを提供します。私の状況では、非同期 API 呼び出しを使用すると高速に実行されることがわかっています。このため、同期呼び出しを強制する、よりクリーンで使いやすいラッパー API を開発者に提供したいと考えています。

これが非同期呼び出しです

db.executeSql(sqlStatement, function(result) {
  // do something with result
});

そして、これが私ができるようにしたいことです

var result = dbWrapper.executeSql(sqlStatement);
// do something with result

これを行うための設計パターン/方法はありますか? 書かれた、またはコード例にリンクされていることが望ましいです。ターゲット プラットフォーム/ブラウザは、iPhone の Mobile Safari です。

ありがとうございました

4

7 に答える 7

10

申し訳ありませんが、JavaScript は、非同期のものを同期的に、またはその逆に動作させるための言語プリミティブ (スレッドやコルーチンなど) を提供していません。

通常* 1 つの実行スレッドのみを取得するため、リクエストの作成につながる呼び出しのスタックが完全に解明されるまで、タイマーまたは XMLHttpRequest readystatechange からコールバックを取得することはできません。

要するに、実際にはできません。リンクした WebKit ページでネストされたクロージャーを使用するアプローチは、この状況でコードを読みやすくする唯一の方法です。

*: 役に立たず、一般的にバグと見なされるあいまいな状況を除いて

于 2008-10-18T12:31:04.687 に答える
8

StratifiedJS を使用すると、まさにそれを行うことができます。

ブラウザ ストレージに適用する方法に関する記事もあります: http://onilabs.com/blog/stratifying-asynchronous-storage

そして、これはhttps://gist.github.com/613526を使用するStratified JavaScriptライブラリです

例は次のようになります。

var db = require("webdatabase").openDatabase("CandyDB", ...);
try {
  var kids = db.executeSql("SELECT * FROM kids").rows;
  db.executeSql("INSERT INTO kids (name) VALUES (:name);", [kids[0]]);
  alert("done");
} catch(e) {
  alert("something went wrong");
}

少し遅いかもしれませんが、当時はこの技術は存在しませんでした;)

于 2011-01-13T15:06:53.353 に答える
4

次のようなことを試すことができます:

function synch()
{
    var done = false;
    var returnVal = undefined;

    // asynch takes a callback method
    // that is called when done
    asynch(function(data) {
        returnVal = data;
        done = true;
    });

    while (done == false) {};
    return returnVal;
}

ただし、非同期メソッドの実行中はブラウザがフリーズする可能性があります...

または、ナラティブJavaScriptをご覧ください。ナラティブJavaScriptは、非同期イベントコールバックのブロック機能を有効にするJavaScript言語の小さな拡張機能です。これにより、非同期コードが読みやすく、理解しやすくなります。

http://neilmix.com/narrativejs/doc/index.html

マイク

于 2010-01-05T03:45:59.690 に答える
1

jQuery Ajax を使用している場合: $.ajax()

asynch の属性を false に設定すると、サーバーへの同期 ajax リクエストが送信されます。

于 2008-10-18T11:30:31.800 に答える
1

非同期APIも備えたGWT RPCを使用しています。シリアルで複数の非同期呼び出しを行うために現在使用しているソリューションは、呼び出しチェーンです。

callA(function(resultA) {
    callB(resultA, function(resultB) {
        callC(); //etc.
    });
});

このネストされたアプローチは、あなたが望むものを達成しますが、冗長で初心者には読みにくいです。私たちが調査したアプローチの 1 つは、必要な呼び出しをスタックに追加し、それらを順番に実行することです。

callStack = [
    callA(),
    callB(),
    callC()
];

callStack.execute();

次に、コールスタックは次を管理します。

  1. 呼び出しを順番に呼び出す (つまり、最初の例の配線)
  2. ある呼び出しから次の呼び出しに結果を渡す。

ただし、Java には関数参照がないため、コール スタックの各呼び出しには匿名クラスが必要になるため、そのような解決策には至りませんでした。ただし、javascript の方が成功する可能性があります。

幸運を!

于 2008-10-18T12:26:33.853 に答える
0

これが適切な場所かどうかはわかりませんが、Firefoxで同期呼び出しを行うための答えを探してここにいます。解決策は、onreadystatechangeコールバックを削除し、直接呼び出しを行うことです。これは私が見つけたものであり、私のソリューション はRESTサービスと同期してコールバックします

于 2011-01-26T19:04:35.797 に答える
0

これは実際にはdbクエリの同期操作を実装していませんが、これは管理を容易にするための私のソリューションでした。基本的に、呼び出し元の関数をコールバック関数として使用し、結果の引数をテストします。関数が結果を受信した場合は解析し、そうでない場合は、クエリメソッドへのコールバックとして自身を送信します。

 render: function(queryResults){
  if (typeof queryResults != 'undefined'){
   console.log('Query completed!');
   //do what you will with the results (check for query errors here)

  } else {
   console.log('Beginning query...');
   this.db.read(this.render); //db.read is my wrapper method for the sql db, and I'm sending this render method as the callback.
  }
 }
于 2011-01-10T00:33:47.250 に答える