从 Mongoose 承诺返回响应

Posted

技术标签:

【中文标题】从 Mongoose 承诺返回响应【英文标题】:Returning response from Mongoose promise 【发布时间】:2016-11-28 00:17:26 【问题描述】:

从这个问题跟进 > Stopping response if document isn't found,因为有人建议我使用 Promise。

所以基本前提,如果我们在数据库中找不到 ID,我希望节点返回“找不到 ID”消息。

v1.post("/", function(req, res) 

    // If the project_id isn't provided, return with an error.
    if ( !("project_id" in req.body) ) 
        return res.send("You need to provide Project ID");
    

    // Check if the Project ID is in the file.
    helper.documentExists( ProjectsData, project_id: req.body.project_id )
        .then(function(c) 
            if ( c == 0 ) 
                return res.send("The provided Project Id does not exist in our database.");
             else 
                var gameDataObj = req.body;

                GameData.addGameId(gameDataObj, function (err, doc) 
                    if (err) 
                        if (err.name == "ValidationError") 
                            return res.send("Please send all the required details.");
                        
                        throw err;
                    ;

                    res.json(doc);
              )
        ;
    );
);

还有 helper.documentExists

module.exports = 
    documentExists: function(collection, query) 
        return collection.count( query ).exec();
    ,
;

但脚本在此之后继续运行并打印“未找到所需数据”。

Output:
    required data not found
    1

我正在使用原生 ES6 Promises。

var mongoose = require("mongoose");
    mongoose.Promise = global.Promise;

编辑:包括整个获取路线。 (稍后会修复那些抛出错误)

【问题讨论】:

console.log("required data not found"); 将运行任何计数,因为它超出了承诺然后回调。 哦。我假设 Promise 会在它下面的任何东西之前运行。我的假设错了吗?我应该在 else 块下添加其余的逻辑吗? 是的,你应该这样做。请参阅我的答案以获得一些见解! 如果 Promise 让你的代码等待它们,那会让它们变得毫无用处,不是吗? ;) 取决于你的依赖。基于此,您可以分支代码。这可以帮助您注意只有关键区域等待 promise 被解决,而其他区域则继续不受干扰。 【参考方案1】:

您的代码基本上会导致:

ProjectsData.count().then(...);
console.log("required data not found");

所以,第二个console.log() 当然会运行并打印。 .then() 处理程序中发生的任何事情都不会运行,直到 console.log() 已经运行很久之后。而且,即便如此,它也无法阻止其他代码运行。 Promise 不会让解释器“等待”。它们只是为您提供协调异步操作的结构。

如果你想用 Promise 进行分支,那么你必须在 .then() 处理程序内部进行分支,而不是在它之后。


你没有充分展示你正在做的其他事情,不知道如何推荐一个完整的解决方案。我们需要查看您请求的其余部分,以帮助您根据异步结果进行正确的分支。


你可能需要这样的东西:

ProjectsData.count( project_id: req.body.project_id ).then(function(c) 
    if ( c == 0 ) 
        return res.send("The provided Project Id does not exist in our database.");
     else 
        // put other logic here
    
).catch(function(err) 
    // handle error here
);

【讨论】:

添加了一个可能的解决方案,但我们确实需要查看其余的相关代码才能知道您实际尝试做什么。 无法在评论中发布整个代码,所以我将尝试对其进行过渡>检查项目是否存在>如果是,请检查提供的数据是否有效>如果是,将文档添加到mongodb收藏。 @DragoonHP - 我要求您在问题中使用“编辑”以在其中包含相关代码。当您展示整个问题并展示真实代码时,我们可以提供更全面的帮助。 好的,我编辑了它。对不起,所有的混乱。并感谢您的所有帮助。真的很欣赏。 :) @DragoonHP - Iceman 已经纠正了他们对我所说的错误解释的回答。如果您的代码正在运行,并且您现在了解原因,那么您就大功告成了。【参考方案2】:
#######POINT 1#########
ProjectsData.count( project_id: req.body.project_id )

    .then(function(c) 
        #######POINT 3#########
        if ( c == 0 ) 
            console.log("1");
            return res.send("The provided Project Id does not exist in our database.");
            console.log("2");
        
    );
#######POINT 2#########
//some other logic
console.log("required data not found");

遵循异步工作流程:在 POINT 1 之后,将创建 Promise 并附加您的处理程序。现在 POINT 2 将继续,而(在未来的某个时间,promise 得到解决,您到达 POINT 3。

由于我对您的工作流程/目的的了解有限,我只想将 POINT 2 代码放在 POINT 3 的 ifelse 中(正如您在 cmets 中正确猜到的那样)。 编辑:感谢@jfriend00 指出我之前版本的答案中的一个严重错误。

【讨论】:

@DragoonHP - 这个答案是错误的。绝对保证此代码的输出将是“未找到所需数据”,然后由于return 而不会命中“1”和“2”。所有.then() 处理程序都保证在未来时钟滴答(根据promoise 标准)上是异步的,所以点2 总是在1、2 和3 之间首先到达。 @jfriend00 你是对的。承诺只会在下一个滴答声中达到最佳状态!

以上是关于从 Mongoose 承诺返回响应的主要内容,如果未能解决你的问题,请参考以下文章

无法得到我在 nodejs / mongoose / bluebird 中返回的承诺

如何从 saveAsync 返回一个 Mongoose 对象?

如何使用带有 Mongoose 和 ES6 承诺的 Graphql 中的 find 来解析多条记录

Mongoose find().exec() 承诺问题 [重复]

无法从 Mongoose 模型中获取文档“find”承诺

使用带有 async/await 的 mongoose 承诺