功能返回不工作

时间:2016-12-09 19:58:57

标签: 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

我已经检查了几页与Stack Overflow相关的问题,这些问题与使用回调,async(节点模块),如何正确返回函数中的值等有关...但是没有一个让我感到惊讶更接近访问函数外的currentRunId。

在我的函数中使用Mongo查询会使这个问题变得更复杂吗?

2 个答案:

答案 0 :(得分:2)

对于后来遇到这种情况的人start by reading this answer

我已经处理了几次,所以我理解沮丧。您正尝试通过执行以下操作来混合同步和异步代码:

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

麻烦的是,在调用getRunID()之后立即调用console.log('Run_ID:'+ currentRunId),将其分配给当前的RunID,并在console.log之后解析getRunID()('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
*/

尝试保存到您的计算机并运行:

node test.js

  

在我的函数中使用Mongo查询会使这个问题变得更复杂吗?

不,您只需要将查询结果传递给承诺或回调,以便您可以在其他地方使用结果。

我希望这有帮助!

编辑:OP在评论中添加了以下代码,我将尝试分解并解决。

  

不幸的是,使用getRunIdB导致回调未定义并且使用getRunIdC导致currentRunId未定义

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.
}) 

答案 1 :(得分: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); 
相关问题