Mongoos, Callbacks и Bears .. О, мой. Не могу получить значения:

1

Добрый день,

Я убежден, что я запутался в кошмаре обратного вызова, пытаясь получить простые значения из файла 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": "Ожидание одобрения"}?

Спасибо за любую обратную связь, которая помогает решить эту проблему.

  • 0
    Хорошо, я получил свои результаты, но оставил меня любопытным без немедленного ответа ... поэтому, когда я изменяю тест var на пустой массив, например, var test = []; а затем нажмите возвращаемое значение для test [], оно заполняется нормально, и тогда я могу получить значение, как я хочу, вне функции обратного вызова. Но почему .push отличается от = в асинхронном назначении под миром? лол? Спасибо за любые отзывы.
  • 0
    Разница в том, что вы передаете ссылку на ваш массив, а не на null . Этот массив заполняется после возврата вашей функции, которой вы никогда не должны доверять, поскольку нет никаких гарантий относительно времени заполнения массива. См. Мой ответ ниже для более подробного объяснения проблемы.
Теги:
callback
express
handlebars.js

1 ответ

0
Лучший ответ

В первом примере не гарантируется правильность отображения 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);
});

Внедрение этих изменений гарантирует, что у вас нет каких-либо условий гонки в вашем коде, и все будет выполняться, когда вы захотите, каждый раз.

  • 0
    Комментарий к первому примеру: наверное, это объясняет, почему иногда я загружаю страницу .hbs, а мои элементы не загружаются. Это случается редко, но определенно заметно, и может показать это с обновлением / повторным посещением.
  • 0
    Я внес изменения в соответствии с вашими рекомендациями и вижу заметное улучшение загрузки страницы, и, надеюсь, исправит периодическую неправильную загрузку входящего {{history}}. Спасибо! Подход обещания возвращает горстку ([obj Obj] [obj Obj], false), из которой я не могу извлечь ничего полезного. Возможно, я что-то упустил. Я пытаюсь подсчитать, сколько элементов в модели БД, которые содержат «Ожидание утверждения» во всех ключах «repairstatus», но преодолевает эти препятствия. Спасибо @Christian за помощь в разъяснении моих dewzies.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню