2016-12-09 4 views
1

Я работаю в узле и пытаюсь загрузить следующую последовательность из моего db. Я могу получить доступ к db, загрузить и вернуть последовательность в моей функции, но я не могу получить к ней доступ за пределами функции.Функция Возврат не работает

function getRunId() { 
     counters.findOne({_id: 'Run_ID'}, function(err, resp) { 
      if(err) { 
       console.log(err); 
      } 
      console.log('Seq: ' + resp.sequence); // Console Output = Seq: 1234 
      return resp.sequence; 
     }); 
    }; 

    var currentRunId = getRunId(); 
    console.log('Run_ID: ' + currentRunId); // Console Output = CRID: undefined 

Я проверил несколько страниц стоит проблем с переполнением стека, связанных с использованием, асинхронной (модуль узла) Обратный вызов, то как правильно возвращать значения в функции, и т.д ... но ни один из них не получить меня ближе к доступ к currentRunId за пределами функции.

Этот вопрос осложняется использованием запросов Mongo внутри моей функции?

+0

'getRunId()' ничего не возвращает, поэтому 'currentRunId' всегда будет неопределенным. Оператор return в вашем коде предназначен для функции, которую вы отправляете в 'counters.findOne()'. Его документация должна рассказать вам, как ее использовать. – Biffen

+0

Я уже проверил [документацию] (https://docs.mongodb.com/v3.0/tutorial/create-an-auto-incrementing-field/) и рекомендовал примеры для этого. Рекомендация выглядит как ответ Далорзо ниже, но, к сожалению, это тоже не работает. – Fairplay89

ответ

1

Для тех, кто спотыкаясь об этом позже, start by reading this answer.

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

var currentRunId = getRunId(); 
console.log('Run_ID: ' + currentRunId); 

Беда в том, что console.log («Run_ID:» + currentRunId) вызывается сразу после вызова getRunID(), назначив ее текущий RunID и getRunID() решает после console.log ('Run_ID:' + currentRunId), в результате чего переменная currentRunId будет неопределенной.

Но у вас есть несколько вариантов решения этой проблемы. Первый вариант - вернуть обратный вызов и вместо этого регистрировать результаты обратного вызова. Вариант 2 - использовать обещание ES6. Чтобы использовать опцию 2, вам нужна узловая версия 7, и вам нужно использовать «use strict» в вашем коде.

Вот 3 примера, построенные вокруг функции заглушки, которая подменяет результаты findOne(). Функция getRunIdA() - это ваша функция, а getRunIdB и getRunIdC - два примера решений вашей текущей проблемы.

'use strict' 

// A function stub which represents a simplified version of findOne. 
// Accepts callback and returns a callback with the results of data 
function findOne (callback) { 
    var data = { 
    sequence: 6 
    } 
    return callback(null, data) 
} 

// This is a simplified version of your function, which reproduces the undefined result 
function getRunIdA() { 
    findOne(function (err, resp) { 
    if (err) { 
     console.log(err) 
    } 
    console.log('Seq: ' + resp.sequence) 
    return resp.sequence 
    }) 
} 

// This is your function with a callback 
function getRunIdB (callback) { 
    findOne(function (err, resp) { 
    if (err) { 
     console.log(err) 
    } 
    console.log('Seq: ' + resp.sequence) 
    return callback(resp.sequence) 
    }) 
} 

// This is your function with a promise 
var getRunIdC = new Promise(function (resolve, reject) { 
    resolve(findOne(function (err, resp) { 
    if (err) { 
     console.log(err) 
    } 
    return resp.sequence 
    })) 
}) 

// Invoke your funciton; get undefined 
var currentRunID = getRunIdA() 
console.log('Run_ID: ' + currentRunID) // Run_ID: undefined 

// Invoke getRunIdB using callback, get 6 
getRunIdB(function (id) { 
    console.log('Run_ID: ' + id) // Run_ID: 6 
}) 

// Invoke getRunIdC with a promise; get 6 
getRunIdC.then(function (currentRunID) { 
    console.log('Run_ID: ' + currentRunID) // Run_ID: 6 
}) 

/* 
results for all 3: 

Seq: 6 
Run_ID: undefined 
Seq: 6 
Run_ID: 6 
Run_ID: 6 
*/ 

Дайте это попробовать, экономя на вашей машине и эксплуатации:

узел test.js

Is this issue further complicated by the use of Mongo queries inside my function?

Нет, вам просто нужно передать результаты вашего запроса к обещание или обратный вызов, чтобы вы могли работать с результатами в другом месте.

Надеюсь, это поможет!

Редактировать: OP добавил в комментарий следующий код, который я попытаюсь сломать и адрес.

Unfortunately, using getRunIdB results in callback is not defined and using getRunIdC results in currentRunId is not defined

var currentRunID = ''; 
var getRunId = new Promise(function (resolve, reject) { resolve(counters.findOne({_id: 'Run_ID'}, function (err, resp) { 
    if (err) { 
    console.log(err) 
    } 
    return resp.sequence; 
    })) 
}); 
getRunId.then(function (res) { 
    console.log('Run_ID: ' + res.sequence) // Run_ID: 1234 
    currentRunID = res.sequence; 
}) 
console.log(currentRunID); // currentRunID is not defined 

Заканчивать an answer I gave to a similar question для получения более подробной информации о модели параллельности JS. Проще говоря, функция getRunID() выполняет асинхронный код. Это означает, что getRunID() не встает в очередь сообщений, которая определяет, какой порядок javascript будет выполняться до тех пор, пока не будут выполнены обратные вызовы. Таким образом, когда вы регистрируете currentRunID за пределами функции .then(), результаты не определены, поскольку currentRunID не определен.

Я думаю, что в конечном счете то, что ОП пытается сделать это экспортировать результат функции так, что-то можно сделать с этими результатами, это должно быть сделано в течение обратного вызова следующим образом:

getRunId.then(function (res) { 
    // Do stuff with the run ID here. 
}) 
+0

Прежде всего, благодарю вас за то, что нашли время ответить. К сожалению, использование getRunIdB приводит к тому, что 'callback не определен', и используя результаты getRunIdC в' currentRunId не определен'. – Fairplay89

+0

'var currentRunID = ''; вар getRunId = новый Promise (функция (решительность, отвергают) { решительность (counters.findOne ({_ ID: 'Run_ID'}, функция (эээ, соответственно) { если (ERR) { console.log (ERR) } return resp.sequence; })) }); getRunId.then (функция (RES) { console.log ('Run_ID:' + res.sequence) // Run_ID: 1234 currentRunID = res.sequence; }) console.log (currentRunID); // currentRunID не определен' – Fairplay89

+0

Привет, Fairplay89, если вы посмотрите снова, вы увидите, что обещание, что вы использовали _did_, состоит в том, что вы пытаетесь зарегистрировать результаты текущей переменной RunID вне функции обратного вызова, переменная назначается. Вы не можете этого сделать из-за модели параллелизма JavaScript. Вы также, возможно, не должны этого делать, потому что присвоение результатов глобальному не является большой практикой. Я думаю, что вы пытаетесь сделать так, чтобы вы могли работать с результатами getRunID() где-то еще в вашем коде. Я добавил дополнительную информацию к своему сообщению. Позвольте мне знать, если это помогает. –

1

Вы только возвращение на функцию обратного вызова, а не на фактической функции .. Измените код следующим образом:

function getRunId() { 
     var result = counters.findOne({_id: 'Run_ID'}, function(err, resp) { 
      if(err) { 
       console.log(err); 
      } 
      console.log('Seq: ' + resp.sequence); // Console Output = Seq: 1234 

     return resp.sequence; 
    }); 
    return result; //<-- return result of your function is here 
}; 

var currentRunId = getRunId(); 
console.log('Run_ID: ' + currentRunId); 
+0

Прошу прощения, но это не так, как работает async. Вы проверили это? – mkhanoyan

+0

Я пробовал эту настройку, но это приводит к 'TypeError: Преобразование круговой структуры в JSON'. – Fairplay89

Смежные вопросы