У меня был цикл, который вызывал вызовы базы данных (sqlite3), чтобы уменьшить количество ресурсов в обратном вызове. Он отлично работал, уменьшая все, что у «partUsed» было на 1.Использование прототипа для добавления свойства к функции приводит к тому, что параметры функции становятся неопределенными
В среднем может быть от 1 до 60 элементов массива, поэтому этот цикл будет создавать от 1 до 60 задач асинхронной работы в быстрой последовательности. Подпись функций обратного вызова (ошибка, строка), определяемая привязкой JS к sqlite3. Я не могу его изменить.
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++;
}
В containes массива много дубликатов элементов и сортировка массива будет, конечно, разместить их все рядом друг с другом так, что немного больше логики может создать подсчет количества предметов «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
* «Закрытие не будет работать (проверено), потому что по времени срабатывания обратных вызовов счетчик является значением последнего счета в цикле.» * ... Затем вы делали это неправильно. – user2736012
Когда вы изменяете 'selectCallBack.prototype.count' в цикле, все объекты, созданные из' new selectCallBack() ', будут видеть обновление. Другими словами, объект '.prototype' разделяется между всеми экземплярами, и поэтому все они наблюдают обновления. Почему бы просто не поместить свойство непосредственно на объект, который вы создаете? – user2736012
... если третий аргумент 'DB.get()' должен быть функцией обратного вызова, вы не передаете его, когда вы делаете 'new selectCallback', если один из них не возвращается из' selectCallback' при его вызове. – user2736012