Глобальные переменные, вызывающие сбой в индексном файле nodejs - PullRequest
0 голосов
/ 02 июля 2018

Итак, я объявляю переменную, которую я могу использовать где угодно:

// Global Variables
app.use(function (req, res, next) {

  // Mob Database
  db.query('SELECT * FROM mobs').then(results => {
    req.mobs = results;
    res.locals.mobs = req.mobs;
  });

  next();
});

Вот где я его использую:

<select id="monster">
 <% for (var i = 0; i < mobs.length; ++i) { %>
  <option name="mobs" value="<%= mobs[i].id %>"><%= mobs[i].name %></option>
 <% } %>
</select>

Он отлично работает при первой загрузке, переходя назад и вперед в моих представлениях, однако, как только я обновляюсь пару раз, он вылетает и говорит «мобы не определены»: Вот полный журнал ошибок:

    74|                 <form name="mobget">
    75|                   <select id="monster">
 >> 76|                   <% for (var i = 0; i < mobs.length; ++i) { %>
    77|                       <option name="mobs" value="<%= mobs[i].id %>"><%= mobs[i].name %></option>
    78|                   <% } %>
    79|                   </select>

mobs is not defined
    at eval (eval at compile (/home/kogadmin/www/node_modules/ejs/lib/ejs.js:618:12), <anonymous>:62:28)
    at returnedFn (/home/kogadmin/www/node_modules/ejs/lib/ejs.js:653:17)
    at tryHandleCache (/home/kogadmin/www/node_modules/ejs/lib/ejs.js:251:36)
    at View.exports.renderFile [as engine] (/home/kogadmin/www/node_modules/ejs/lib/ejs.js:482:10)
    at View.render (/home/kogadmin/www/node_modules/express/lib/view.js:135:8)
    at tryRender (/home/kogadmin/www/node_modules/express/lib/application.js:640:10)
    at Function.render (/home/kogadmin/www/node_modules/express/lib/application.js:592:3)
    at ServerResponse.render (/home/kogadmin/www/node_modules/express/lib/response.js:1008:7)
    at /home/kogadmin/www/server.js:112:9
    at Layer.handle [as handle_request] (/home/kogadmin/www/node_modules/express/lib/router/layer.js:95:5)

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

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

Проблема здесь в том, что порядок выполнения не гарантирован, вы можете вызывать next () до завершения запроса. По сути, мы участвуем в гонке кода в next () с помощью запроса db.

Именно поэтому мобы не определены, иногда запрос еще не завершен.

Я бы предложил звонить только после завершения запроса. например,

// Global Variables
app.use(function (req, res, next) {

    // Mob Database
    db.query('SELECT * FROM mobs').then(results => {
        req.mobs = results;
        res.locals.mobs = req.mobs;

        // Now it's safe to call next.
        next();

     }).catch((err) => {
         console.error('Error occurred during query: ', err);
         // Consider sending back a 500 here.
     })
});
0 голосов
/ 04 июля 2018

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

map.js

var hashmapSession = {};

exports.sess = {
  set : function(key, value){
    hashmapSession[key] = value;
  },
  get : function(key){
    return hashmapSession[key];
  },
  delete : function(key){
    delete hashmapSession[key];
  },
  all : function(){
    return hashmapSession;
  }
};

Теперь используйте существующий код для извлечения данных из базы данных, но вместо этого сохраните его в res.locals, используйте приведенную выше карту. Например:

var hashmap = require('./hashmap');
app.use(function (req, res, next) {
  // Mob Database
  db.query('SELECT * FROM mobs').then(results => {
     if(results)
      hashmap.sess.set('global', results);
  });

  next();
});

Теперь создайте конечную точку для рендеринга сохраненных данных. Например:

app.get('/showData', function(req, res){
  var data = hashmap.sess.get('global');
  res.render('main', data);
})

Примечание. Здесь 'main' - это ваш файл main.ejs.

...