Добрый день,
Я убежден, что я запутался в кошмаре обратного вызова, пытаясь получить простые значения из файла Mongoos.count, передавая {query}. Я могу получить значение и увидеть его в консоли, изнутри обратного вызова, но попытка получить это из асинхронной настройки обратного вызова - это удар по моему улью.
Я использую Node.js и Express, пытаясь выполнить некоторые, казалось бы, простые задачи получения простого числа из моей модели, "Job" для запроса выше,
У меня есть аналогичный сценарий, который работает в одном экземпляре router.get и способен записывать переменную вне функции родительского вызова. так:
router.get('/repairmanager', ensureAuthenticatedAdmin, function(req, res) {
var list = []; // This list populates ok even within the Job.find callback nest hole
if(filter == 'userid' && query != "" || null){
Job.find( {'userid' : new RegExp('^'+query+'$', "i")} )
.then( function(doc){
//console.log(doc);
doc.forEach(function(job){
list.push(job); //<--- Populates just fine and can
// see in res.render {{history}}
});
});
res.render('repairmanager', { history: { 'data' :list}} );
}
)};
Вышеупомянутый код работает и способен заполнять массив списка...
НО, когда я применяю аналогичный сценарий, пытаясь получить другое значение из
function pendingCount(){
var test = null;
Job.count({'repairstatus': 'Pending Approval'}, function(err, cb){
test = cb;
console.log('test inside callback : ' + test);
});
console.log('test ourside callback : ' + test);
return test;
};
Я не могу на всю жизнь получить тестовую переменную, чтобы заполнить что-то-никогда и не вернуть ее в функцию pendingCount()
Я знаю, что есть песня и танец о функциях обратного вызова асин, но.. но..
Почему массив списков можно увидеть и записать в другую функцию Mongoos? а не в моей другой функции, пытаясь получить простой счет запроса {"repairstatus": "Ожидание одобрения"}?
Спасибо за любую обратную связь, которая помогает решить эту проблему.
В первом примере не гарантируется правильность отображения list
. Если это правильно рендеринг, это удача (Job.find
обещание и res.render
находятся в состоянии гонки, участвуя в гонке для достижения list
. res.render
просто выигрывает в этом случае. Это может быть не так, если задана другая сеть условий, аппаратных условий или какой-либо другой случайной причины).
Если вы хотите быть на 100% уверенным, что ваш res.render
вызывается в правильный момент времени каждый раз, вам нужно принять дополнительные меры предосторожности.
В первом примере вам нужно переместить res.render
в then
обратный вызов:
Job.find( {'userid' : new RegExp('^'+query+'$', "i")} ).then( function(doc){
//console.log(doc);
doc.forEach(function(job){
list.push(job); //<--- Populates just fine and can
// see in res.render {{history}}
});
// render here
res.render('repairmanager', { history: { 'data' :list}} );
});
Для вашего второго примера вы не сможете просто вернуть test
, так как это значение будет заполнено асинхронно. Вместо этого вам следует возвратить Promise
, которое решит нужное значение.
Начиная с Mongoose> = 4.0, count
вернет Promise
по умолчанию, так что вы можете просто вернуть результат count
вызовов:
function pendingCount(){
return Job.count({'repairstatus': 'Pending Approval'});
};
Чтобы использовать pendingCount
, вы относитесь к нему как к Promise
:
pendingCount().then(function(count) {
console.log(count);
});
Внедрение этих изменений гарантирует, что у вас нет каких-либо условий гонки в вашем коде, и все будет выполняться, когда вы захотите, каждый раз.
null
. Этот массив заполняется после возврата вашей функции, которой вы никогда не должны доверять, поскольку нет никаких гарантий относительно времени заполнения массива. См. Мой ответ ниже для более подробного объяснения проблемы.