例:
2 行のデータベース テーブル:
rowid name qty date
1 milk 3 8/25
2 milk 40 8/30
5 つの牛乳アイテムを差し引く在庫トランザクションは、最も古い牛乳を最初に使用して実行する必要があります。
例えば
行 ID 1 を選択してコールバックを待ち、その中で行 ID 1 を削除します。その数量は 0 になり、消費されます。
新規削除数量 = 5 - 3 = 2。0 ではないため、別の選択を行う必要があります。
行 ID 2 を選択
そのコールバックを待ち、そこでrowid 2を更新してqty = 38に設定します。
sqlite バインディングのシリアル化機能は、2 つの Select のみをシリアル化します。最初の Select とそのコールバックが完了するまで、2 番目の Select が必要であることを知る方法はありません。最初のセレクトが不十分な数量を提供したことに気付いたのはその時だけです。
純粋な JavaScript を使用して最初の Select とそのコールバックをシリアル化する方法 - JQuery やその他のライブラリは使用しません。
疑似コードの例を次に示します。これは、問題を説明するために考えられる最小の例です。
db は、成功した sqlite データベースのオープン呼び出しの結果であると仮定します。
var deletionQty = 5;
function selectCallBack(error, row) {
// Assume no error.
if (deletionQty >= row.qty) {
// Delete row.rowNum
deletionQty -= row.qty; // Need to get the next table row to deduct remaining inventory from it.
} else {
// Update row.rowNum -> set qty = qty - deletionQty
deletionQty = 0; // Done!
}
}
while (deletionQty > 0) {
db.get("SELECT rowid AS rowNum, qty FROM Inventory ORDER BY date LIMIT 1", selectCallBack);
}
問題は、while のスコープ内では削除 Qty の値が変更されないため、while が継続的に実行されることです。コールバックのみがそれを変更します。これらは非同期イベントであるため、while ループが実行されます。たとえば、コールバックが DeleteQty の値を変更する前に 100 回実行されます。1 対 1 の関係 (同期関係) があり、db.get が 1 つだけ実行され、そのコールバックが次の while ループ サイクルの前に実行される場合、すべてが正常に機能します。問題となる新しいコールバックの設定を継続的に実行できるようにするのは、非同期遅延コールバックです。