我在 Node 中工作并尝试从我的数据库中加载下一个序列。我可以在函数内访问数据库、加载和返回序列,但无法在函数外访问它。
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
我已经检查了几页与使用回调、异步( Node 模块)、如何在函数中正确返回值等相关的 Stack Overflow 问题...但是没有一个能让我更接近于在功能。
在我的函数中使用 Mongo 查询会使这个问题变得更加复杂吗?
最佳答案
对于后来遇到此问题的任何人,start by reading this answer .
我已经处理过几次这个问题,所以我理解这种挫败感。您正在尝试通过这样做来混契约(Contract)步和异步代码:
var currentRunId = getRunId();
console.log('Run_ID: ' + currentRunId);
问题是 console.log('Run_ID: ' + currentRunId) 在调用 getRunID() 后立即调用,方法是将其分配给当前 RunID,而 getRunID() 在 console.log('Run_ID: ' + currentRunId) 之后解析), 导致 currentRunId 变量未定义。
但是,您有一些选择来处理这个问题。选项一是返回回调,并记录回调的结果。选项 2 是使用 ES6 promise。要使用选项 2,您需要 Node 版本 7,并且需要在代码中使用“use strict”。
这里有 3 个围绕函数 stub 构建的示例,该函数 stub 欺骗了 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
*/
通过保存到您的机器并运行来尝试一下:
Node 测试.js
Is this issue further complicated by the use of Mongo queries inside my function?
不,您只需要将查询结果传递给 promise 或回调,以便您可以在其他地方处理结果。
希望对您有所帮助!
编辑: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 执行的顺序,直到它的回调完成。因此,当您在 .then() 函数之外记录 currentRunID 时,结果是未定义的,因为 currentRunID 是未定义的。
我认为最终 OP 试图做的是导出函数的结果,以便可以用这些结果完成某些事情,这需要在回调中完成,如下所示:
getRunId.then(function (res) {
// Do stuff with the run ID here.
})
关于javascript - 函数返回不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41067943/