无法通过递归调用node.js中的函数从promises获得响应

Posted

技术标签:

【中文标题】无法通过递归调用node.js中的函数从promises获得响应【英文标题】:Unable to get response from promiese with recursively calling the function in node.js 【发布时间】:2018-05-04 12:16:11 【问题描述】:

使用 node.js Q 承诺库我怀疑递归调用函数是否有用。我尝试了两种方法来解决我的问题。在第一种方法中,我尝试直接从递归函数返回,而在第二种方法中,我尝试使用 Q Promise 库。

这是我调用递归函数并期待响应的代码。

function getSearchedUserInTree(userId,body)
    var deferred = Q.defer();
    var loggedInUserId = userId;    
    var searchUserIdSql =  "SELECT rc.user_id,CAST(b.node_id AS CHAR) AS node_id FROM refer_codes AS rc LEFT JOIN btrees AS b ON b.user_id=rc.user_id WHERE rc.refer_code='"+body.refer_code+"'";
    connection.query(searchUserIdSql, function (err, result,field)         

        var getLoggedInNode = "SELECT CAST(b.node_id AS CHAR) AS node_id FROM btrees as b WHERE b.user_id='"+loggedInUserId+"'";
        connection.query(getLoggedInNode, function (err, loggedResult,field) 
            helper.trackRelation(loggedResult[0].node_id,result[0].node_id,function(err,relationResult)
                if(err) throw err;
                deferred.resolve(relationResult);
            );
        );        
    );

    return deferred.promise;

第一种从带有承诺的“trackRelation()”函数中获取回报的方法。

function trackRelation(parentNode,childNode)
  var deferred = Q.defer(); 
  var childNodeId = bigInt(""+childNode+"");
  var parentNodeId  = bigInt(""+parentNode+"");
  if(bigInt(childNodeId).compare(parentNodeId) == 0)        
    var childSql = "SELECT * FROM users WHERE id='"+childNodeId.toString()+"'";
    connection.query(childSql,function(err,packResult,field)
      console.log(packResult);
      deferred.resolve(status:200,message:'success',packResult);
    );
  else
    /* Detact position */
    if(bigInt(childNodeId).mod(2) == 0)
      var tempParentNodeId = bigInt(childNodeId).divide(2);
    else
      var subResult = bigInt(childNodeId).subtract(1);
      var tempParentNodeId = subResult.divide(2);
     

    /** If reached at top but parent not found **/
    if(bigInt(tempParentNodeId).compare(1) == 0)
      var childSql = "SELECT * FROM users WHERE id='"+tempParentNodeId.toString()+"'";
      connection.query(childSql,function(err,packResult,field)
        console.log(packResult);
        deferred.resolve(status:200,message:'success',packResult);        
      );
    else
      return trackRelation(parentNodeId,tempParentNodeId.toString());
    

  
  return deferred.promise;

从递归函数中获取返回值的第二种方法,直接返回值,没有承诺。

function trackRelation(parentNode,childNode)      
      var deferred = Q.defer();
      var childNodeId = bigInt(""+childNode+"");
      var parentNodeId  = bigInt(""+parentNode+"");      
      if(bigInt(childNodeId).compare(parentNodeId) == 0)
                     
        deferred.resolve(status:200,message:'success',topUserId:childNodeId.toString());
        return childNodeId.toString();
      else
      
        /* Detact position */
        if(bigInt(childNodeId).mod(2) == 0)
          var tempParentNodeId = bigInt(childNodeId).divide(2);
        else
        
          var subResult = bigInt(childNodeId).subtract(1);
          var tempParentNodeId = subResult.divide(2);
        

        /** If reached at top but parent not found **/
        if(bigInt(tempParentNodeId).compare(1) == 0)          
          return tempParentNodeId.toString();
        else
        
          return trackRelation(parentNodeId,tempParentNodeId.toString());
        
      
      return deferred.promise;
    

我没有从这两种方法中得到任何回应。我试图在控制台中打印我需要响应的值,我得到的值与期望的值相同,但无法得到响应的值。

【问题讨论】:

else 的情况下,您永远不会调用deferred.resolve 在我的第一种方法中,我已经使用了 deferred.resolve(status:200,message:'success',packResult); .是不是正确的使用方式? 【参考方案1】:

你不能像从回调中返回的方式从 Promise 中返回值。

您的方法 trackRelation 返回一个应使用 .then() 方法访问其值的承诺。

例子:

trackRelation(args).then(function(res)
     //when the promise resolves, this method is called
, function(err)
     //when the promise rejects, this method is called
);

查看 API 参考页面here。

【讨论】:

感谢 Parijat 的回答,这实际上对我有用。你能解释一下我做错了什么以及如何解决node.js中的此类问题吗?还有一件事,你能告诉我在得到想要的结果后如何停止递归吗? 正如您所说的那样,它对您有用,我将简要解释一下..您为返回承诺的函数做了trackRelation(args,callback)。相反,如果您使用trackRelation(args).then(passCallback, failCallback),它应该可以正常工作。就递归而言,如果您希望使用递归 Promise,请先让递归 Promise 解决,然后再解决当前的 Promise。我的意思是做类似的事情:elsetrackRelation(parentNodeId,tempParentNodeId.toString(),function(res)defer.resolve(res);)

以上是关于无法通过递归调用node.js中的函数从promises获得响应的主要内容,如果未能解决你的问题,请参考以下文章

node.js怎么调用matlab中的函数

如何从 Node.js 中的 API 请求创建响应流?

Node.js fs.readdir 递归目录搜索

Node.js fs.readdir 递归目录搜索

Node.js fs.readdir 递归目录搜索

使用 node.js 从 Google Cloud 函数中的 IncomingMessage 对象读取正文