Для тех, кто спотыкаясь об этом позже, 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.
})
'getRunId()' ничего не возвращает, поэтому 'currentRunId' всегда будет неопределенным. Оператор return в вашем коде предназначен для функции, которую вы отправляете в 'counters.findOne()'. Его документация должна рассказать вам, как ее использовать. – Biffen
Я уже проверил [документацию] (https://docs.mongodb.com/v3.0/tutorial/create-an-auto-incrementing-field/) и рекомендовал примеры для этого. Рекомендация выглядит как ответ Далорзо ниже, но, к сожалению, это тоже не работает. – Fairplay89