Пределы видимости переменной в js

179
27 марта 2018, 03:00

Здравствуйте, пишу REST API на express.js вкупе с базой данных NeDB.js. В одной из при реализации функции получения данных из базы данных я столкнулся с проблемой. Это файл Router.js

const express = require('express');
const Database = require('./Database')
module.exports = class Router   {
    static initialize () {
        this.api = express();
        this.api.get('/classes/:class/:number/:dayOfWeek', (req, res) => {
          console.log('new request ' + req.params.class, req.params.number, req.params.dayOfWeek)
          var lessons = Database.getScheduler(req.params.class, req.params.number, req.params.dayOfWeek);
          res.send(lessons);
      });
        this.api.listen(80);
    }
}

Это файл Database.js

const nedb = require('nedb');
module.exports = class Database {
  static initialize () {
    this.db = new nedb({filename: "scheduler"});
    this.db.loadDatabase();
  }
  static getScheduler (findingClass, findingNumber, dayOfWeek) {
    var data;
    this.db.find({class: findingClass.toString(), number: findingNumber.toString()}, (err, docs) => {
      data = {'lessons' :docs[0].lessons[Number.parseInt(dayOfWeek)]};
      //console.log(data) => "нужные данные"
    });
    //console.log(data) => undefined
    return data;
  }
}

Это файл Main.js

const Router = require('./Router');
const Database = require('./Database');
Database.initialize();
Router.initialize();

Проблема такая, почему в пределах анонимной функции переменная data хранит значение, полученное с базы данных, а за пределами анонимной функции data имеет значение undefined? И как это исправить? Заранее спасибо!

Answer 1

Вам необходимо почитать про асинхронные функции. Проблема заключается в том, что анонимная функция выполняется после того, как выполняется строка:

console.log(data) // undefined

Потому что функция find ожидает ответа от базы, и чтобы не было пустого простоя, код выполняется дальше, а анонимная функция выполнится только тогда, когда данные придут.

Cделайте простой тест:

this.db.find({class: findingClass.toString(), number: findingNumber.toString()}, (err, docs) => {
  console.log('1');
});
console.log('2');

Вы заметите, что скорее всего сначала будет выведено число 2, а только затем 1

READ ALSO
Почему отображаются 3 картинки вместо 4?

Почему отображаются 3 картинки вместо 4?

Не корректно работает плагин isotope(https://isotopemetafizzy

164
Передача функции в другой поток Node JS

Передача функции в другой поток Node JS

При попытке передачи функции в другой поток, она исчезает, а с другими объектами всё работает исправно

226
Сравнение даты и времени (React js)

Сравнение даты и времени (React js)

Подскажите пожалуйста, как правильно сделать сравнение даты и времени? Задача состоит в следующем, одну дату и время я задаю, например (2019-03-26T10:29)...

147