HiNeX
@HiNeX
Web Developer

Как вытащить переменную за рамки функции в JavaScript?

Как можно вытащить данные за рамки вызываемой функции (коллбека)? Или как можно вытащить данные из модели в Mongoose и использовать значения далее в коде?

var items_list;
db.model('items').find({}, function (err, data) {  items_list = data });
console.log(items_list); // undefined
  • Вопрос задан
  • 3408 просмотров
Решения вопроса 1
MarcusAurelius
@MarcusAurelius Куратор тега Node.js
автор Impress Application Server для Node.js
Как раз этого делать не нужно. Вместо этого нужно понять идею асинхронного программирования. Все колбэки исполняются не по месту своего объявления, а тогда, когда к ним приходят данные, поэтому в Вашем примере кода сначала происходит console.log(items_list); а уже потом items_list = data И это хорошо, потому, что не происходит ожидания исполнения коллбеков, не происходит блокирования потока исполнения. Всю синхронную логику обработки полученных в коллбеке данных Вы можете написать прямо в коллбеке, а если нужно реализовать последовательный или параллельный вызов нескольких ассинхронных запросов (все, что связано с вводом/выводом, доступом к базе и файлам, например), то это можно сделать разными способами, самые популярные из них, это библиотека async и промисы. Я использую https://github.com/caolan/async Например:
var async = require('async');
var items_list, users_list;
async.parallel([
    function(callback) { // делаем первый запрос к базе
      db.model('items').find({}, function (err, data) {
        items_list = data;
        callback(); // данные получены, возвращаемся
      });
    },
    function(callback) { // параллельно делаем второй запрос к базе
      db.model('users').find({}, function (err, data) {
        users_list = data;
        callback(); // данные получены, возвращаемся
      });
    }
],
function() {
  // когда оба запроса уже завершены, то мы попадаем сюда
  console.dir({ items: items_list, users: users_list });
});
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
nazarpc
@nazarpc
Open Source enthusiast
Наиболее близкую аналогию тому что вы хотите можно получить с помощью Promises.
Ответ написан
Комментировать
TheCreator
@TheCreator
Бездельник
Гораздо удобнее (и правильнее) писать на async в таком стиле.
var async = require('async');
async.auto({
    'Aitems': function(callback) { // делаем первый запрос к базе
      db.model('items').find({}, function (err, data) {
        callback(err, data); // данные получены, возвращаемся
      });
    },
    'Busers': function(callback) { // параллельно делаем второй запрос к базе
      db.model('users').find({}, function (err, data) {
        callback(err, data); // данные получены, возвращаемся
      });
    }
},
function(err, results) {
  if (err){return console.error(err);} // если будут ошибки - их напишем.
  // ошибок нет, нам доступны результаты каждой операции
  console.dir({ items: results['Aitems'], users: results['Busers'] });
});

У вас есть обработка ошибок, плюс вы уверены, что ваши переменные items_list и user_list не будут изменены где-то ещё, во время обработки запросов. Некрасиво выносить переменные за функцию, которая их изменяет.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы