コールバックの在庫を減らすためにデータベース呼び出し (sqlite3) を実行するループがありました。それは正常に機能し、「使用済みの部分」が 1 減りました。
平均して 1 から約 60 の配列要素が存在する可能性があるため、このループは 1 から 60 の非同期タスクを立て続けに作成します。コールバック関数のシグネチャは、sqlite3 への JS バインディングによって決定される (エラー、行) です。変更できません。
i = 0;
while (i < struct.PortionsUsed.length) {
portionUsed = struct.PortionsUsed[i];
Db.get("SELECT blah blah WHERE portion = ? ORDER BY date LIMIT 1", portionUsed, selectCallBack);
i++;
}
配列には多くの重複要素が含まれており、配列を並べ替えると、もちろん、それらすべてが互いに隣接して配置されるため、もう少しロジックを使用して、1 回の呼び出しで在庫から差し引く "portionUsed" アイテムの数のカウントを作成できます。 60 のタスクを約 10 に減らすと、実行する価値があります。これは、コールバックにカウントを与える必要がありますが、それを提供する一般的なメカニズムがないことを意味します。
コールバックが起動するまでに、カウントはループ内の最後のカウントの値になるため、クロージャーは機能しません (試してみました)。コールバック内で使用できるように、コールバック タスクの作成時に現在の「カウント」を提供する必要があったため、コールバック関数オブジェクトのプロトタイプ拡張機能を使用して、関数ごとに一意の「カウント」をドラッグしようとしました。 Db 呼び出しごとにインスタンス化されたコールバック関数。
struct.PortionsUsed = struct.PortionsUsed.sort(); // Get all identical portion items adjacent to each other.
i = 0;
while (i < struct.PortionsUsed.length) {
// i points at the first portion item, whatever it is.
j = i + 1;
while (j < struct.PortionsUsed.length && struct.PortionsUsed[i] === struct.PortionsUsed[j]) {
++j;
}
// j points at 1 past the last identical portion item.
count = j - i; // count has the number of portions to deduct from inventory.
// Get the oldest Portion row and reduce the qty by the count.
portionUsed = struct.PortionsUsed[i];
if (debug) {console.log('Starting Select for ' + portionUsed + ' - count=' + count);}
selectCallBack.prototype.count = count;
selectCallBack.prototype.portionUsed = portionUsed;
Db.get("SELECT rowid AS rowNum, portion, qty FROM Portion WHERE portion = ? ORDER BY date LIMIT 1", portionUsed, new selectCallBack);
//Db.get("SELECT rowid AS rowNum, portion, qty FROM Portion WHERE portion = ? ORDER BY date LIMIT 1", portionUsed,
// function(error, row) {count; portionUsed; selectCallBack(error, row);});
i = j;
}
(エラー、行) の両方が未定義であるため、コールバックはまったく機能しません。なんで?どうすればこれを修正できますか? コールバック内では、this.count が思い通りに利用できます。
これについてもっと良い方法はありますか?
コールバックは次のとおりです。
function selectCallBack(error, row) {
var count = this.count; // made active ONLY when attempting to use prototype
var portionUsed = this.portionUsed; // made active ONLY when attempting to use prototype
var portion;
if (debug) {console.log('Hit selectCallBack. count=' + count + ' portionUsed=' + portionUsed);}
if (debug) {console.log(typeof error + typeof row);}
if (error !== null) {
if (debug) {console.log('selectCallBack error:\n' + error);}
success = false;
} else {
// real work goes here
}
} // no return statement of any kind.
閉鎖出力:
Starting Select for Coffee - count=5
Starting Select for Hot Tea - count=2
Hit selectCallBack. count=2 portionUsed=Hot Tea
objectobject
Hit selectCallBack. count=2 portionUsed=Hot Tea
objectobject
プロトタイプ アプローチの出力:
Starting Select for Coffee - count=5
Hit selectCallBack. count=5 portionUsed=Coffee
undefinedundefined
selectCallBack error:
undefined
Starting Select for Hot Tea - count=2
Hit selectCallBack. count=2 portionUsed=Hot Tea
undefinedundefined
selectCallBack error:
undefined