【问题标题】:Returning a variable declared inside a Mongoose find()返回在 Mongoose find() 中声明的变量
【发布时间】:2017-07-09 07:47:45
【问题描述】:

我在将 for 循环与 Promise 结合使用时遇到了很多麻烦。本质上,我的工作流程是:

  1. 在 Node.js 中获取一组 Artist 对象,并获取它们的 使用 Mongoose 的传记和 ID。
  2. 使用他们的 ID 获取所有艺术品(更具体地说,所有 艺术作品关键字)由该艺术家创作。
  3. 在自然语言处理器分类器中训练它们(这部分 不是超级相关-只知道我需要访问 biographykeywords 在同一个外部范围内。

但是,我似乎无法在 Mongoose 承诺中使用 bioText 对象,而且我似乎无法从 Mongoose 承诺中返回关键字。

            if (!isBlank(bioText) && bioText){
                bioText = artist.BIO;
                artworkIdArray.forEach((id)=> {
                        console.log(bioText) // <- prints correct values
                        var getKey = function(){
                    var words = Artwork.findById(id).then((artwork)=>{
                        console.log(bioText) // <- empty string
                    if(artwork.artworkKeywords.length > 0){
                        keywords = artwork.artistKeywords;
                        return keywords;
                    }
                }
                )
                return words;    
                }
                t=getKey();
                t.then((t)=>{
                    console.log(t); // <--- always undefined
                })
            }, this);
        }

如您所见,我在退出承诺后尝试 console.log(),但 t 对象始终未定义。

另外,

我知道在我的示例中,bioText 在 Mongoose find() 承诺之前一直可用。但我也不知道如何将 bioText 注入到 Promise 中(因为我可以简单地在 then() 语句中训练分类器。

所以我的帖子基本上是两个问题:

  1. Promises 可以在 then() 内部使用外部变量吗?
  2. 如何返回在 then() 中声明的变量,所以它是 在外部范围内可用?

【问题讨论】:

  • 为什么要在回调函数之外访问变量t?您可以实现类似“评估 t 时,console.log(t)”之类的逻辑,但我看不到这一点。只需将所有后续代码放在回调函数中即可。
  • @R.Saban 我可以这样做,但是如何在 then() 语句中获取我的 bioText 变量?

标签: javascript node.js mongodb mongoose


【解决方案1】:
  1. Promises 可以在 then() 中使用外部变量吗?

是的,但是您必须小心这些变量以后会发生什么。 这就是为什么console.log(bioText) 可能会在 DB 调用之前记录一个值,然后在 DB 响应之后记录 null

我建议您尝试 立即调用 模式以确保该值是预期值:

(function(x){...; console.log(x);})(bioText)
  1. 如何返回在 then() 中声明的变量,使其可用 在外部范围内?

你不能,至少没有复杂的承诺管理,你在这里可能不需要。 这就是为什么t=getKey(); 总是undefined

我认为您希望在继续您的流程之前获得所有值。因此,您应该在单个查询中从 DB 中检索所有内容,然后在回调中调用您的所有代码。

你可以试试这个:

Artwork
    .find({_id: {$in: artworkIdArray}})
    .then( (artworks) => {
        var keywords = [];
        artworks.forEach( (artwork) => {
            if(artwork.artworkKeywords.length > 0)
                keywords.append(artwork.artistKeywords);
        });
        // Now do your job with all the retrieved keywords
    });

【讨论】:

  • 谢谢,但同样的问题仍然存在——我在代码的前面有一堆 bioText 字符串变量。如何在then 语句中使用它们?
  • 您的 bioText 变量是then 语句的范围,所以我不明白您的问题。你得到什么错误?
  • 不是。再看看我的代码——我添加了一些 cmets 来告诉你 bioText 范围在哪里。它是在承诺链开始之前定义的(来自我抓取的另一个结果集)。我没有收到错误,只是我得到一个空字符串值。
  • 非常感谢您回答 #2。 +1 为例。您能否提供一个在 then() 中使用的外部作用域的示例?因为正如您在我的代码 cmets 中看到的那样,在 then() 中 bioText 是空的。
  • 从我在您的代码中可以读到的内容,我假设 bioText 稍后会被取消。所以当then() 被执行时,你的bioText 是空的,而在你调用数据库的那一刻它不是。
猜你喜欢
  • 2020-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多