javascript - 函数返回不起作用

标签 javascript node.js mongodb

我在 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/

相关文章:

javascript - 返回异步数据然后在 Node.js 中同步导出

javascript - 对于混合移动应用程序,FB 应用程序应该具有什么 "SITE URL"?

mysql - Sequelize 验证错误被忽略

javascript - 如何导出仅在异步回调中可用的对象?

javascript - 将逻辑添加到 Mongoose 的 Model ctor 中的最佳实践是什么?

javascript - “this”仅在组件集成测试中未定义

javascript - 为大js包构建脚本

javascript - 将关联帐户的 Stripe 费用 ID 和帐户 ID 公开给客户端是否安全?

javascript - Node.js 添加 'semi-dynamic' 内容的最佳方式

javascript - 计算键值的出现次数