【问题标题】:Problems with asynchronous recursion in Node.jsNode.js 中的异步递归问题
【发布时间】:2017-08-11 17:48:11
【问题描述】:

我对 Node.js 中递归异步请求的行为有疑问。

下面的函数旨在从 MongoDB 返回搜索结果。如果初始搜索结果为空,我将文本拆分为单个单词,然后尝试为每个单词递归 fetchResult(...),将 res 对象作为参数传递。

function fetchResult(text, res){
    var MongoClient = require('mongodb').MongoClient;

    MongoClient.connect(mongoURL + "/search", function (err, db) {

        if(err) throw err;

        db.collection('results', function(err, collection) {

            // search for match that "begins with" text
            collection.findOne({'text':new RegExp('^' + text, 'i')}, function(err, items){

               var result = (items == null || items.result == null) ? "" : items;

                if (result){
                    res.send(result);
                }
                else {
                    // no result, so fire off individual word queries - if any spaces found
                    if (text.indexOf(' ') > -1){
                        // split string into array
                        var textArray = text.split(" ");

                        // recursively process individual words
                        for (index = 0; index < textArray.length; index++) {
                            // ***** RACE CONDITION HERE? *****
                            fetchResult(textArray[index], res);
                        }
                    }
                    else {
                        // just return empty result
                        res.send(result);
                    }
                }
            });
        });
    });
}

我怀疑这可能会导致一些竞争条件,因为对 res 的引用是异步扇出的,当我运行代码并观察到以下错误时证实了这一点:

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)

所以我的问题是:如何实现按顺序执行单个字符串查询的所需递归行为,仅在我们找到第一个结果时返回(或在搜索返回时在流程结束时返回完全没有结果)?

【问题讨论】:

  • 研究应许

标签: javascript node.js asynchronous recursion


【解决方案1】:

您的代码需要重构。

首先,从fetchResult 函数中删除MongoClient.connect 调用。您可以连接一次并存储db 对象以供以后使用。

其次,通过您的方法,您将返回查询中每个单词的响应。我不认为递归调用是去这里的方式。

如果您的第一个查询失败,您将有多个异步查询,并且您需要以某种方式聚合结果......这就是它变得棘手的地方。我对 Mongo 不是很熟悉,但我相信您可以通过使用 find $in 检索一组结果来避免这种情况。见this question,也许有帮助。

【讨论】:

  • 谢谢,我已经分离了连接和集合的创建,所以它现在可以重用了。我现在应该在什么时候关闭连接?
  • 我没有你的代码的全貌,但我想你的 fetchResult 方法是从请求方法中调用的......你可以在那里管理你的连接。
  • 那么将连接创建代码移到调用方法的实际好处是什么?
  • 更简洁的代码...也许您需要它来进行另一个查询,除了fetchResult...就像用户或其他东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-18
  • 2023-03-04
  • 1970-01-01
  • 2013-03-25
  • 2015-02-19
  • 1970-01-01
相关资源
最近更新 更多