node.js - 处理 NodeJS 异步行为

标签 node.js mongodb asynchronous concurrency redis

将 NodeJS 与 MongoDB+Mongoose 结合使用。

首先,我知道异步非阻塞代码的优点。所以我确实处理回调。但最终我遇到了以下问题。

假设我有一个可以由用户随时调用的函数。并且有可能, super “闪电速度”的用户几乎同时调用它两次。

function do_something_with_user(user_id){
    User.findOne({_id:user_id}).exec(function(err,user){ // FIND QUERY
        // Do a lot of different stuff with user
        // I just cannot update user with a single query
        // I might need here to execute any other MongoDB queries
        // So this code is a set of queries-callbacks
        user.save() // SAVE QUERY
    })
}

当然是这样执行的:FIND QUERY、FIND QUERY、SAVE QUERY、SAVE QUERY

这完全破坏了应用程序的逻辑(应该查找查询、保存查询、查找查询、保存查询)。因此,我决定通过为特定用户“锁定”整个函数来防止异步行为(因此函数代码内部仍然是异步的)。

var lock_function_for_user = {}

function do_something_with_user(user_id){
    if(!lock_function_for_user[user_id]){
        lock_function_for_user[user_id] = true
        User.findOne({_id:user_id}).exec(function(err,user){
            // Same code as above
            user.save(function(){
                lock_function_for_user[user_id] = false
            })
        })
    } else {
        setTimeout(function(){
            do_something_with_user(user_id)
        },100) // assuming that average function execution time is 100ms in average
    }
}

所以,我的问题是:这是一个好的实践,好的黑客还是坏的黑客?如果这是一个糟糕的黑客行为,请提供任何其他解决方案。特别是,我怀疑当我们扩展和启动多个 NodeJS 进程时,这一解决方案是否有效。

最佳答案

这是一个非常糟糕的做法,你永远不应该使用计时器来控制代码的流程。

这里的问题称为原子性。如果您需要执行查找-保存、查找-保存,那么您需要以某种方式打包这些操作(事务)。这取决于您使用的软件。在 redis 中,有 multi 和 exec 命令。在 mongodb 中,你有 findAndModify()。另一种解决方案是使用索引。当您尝试保存同一字段两次时,您会收到错误。在 mongoose 的 schemaType 中使用属性“index: true”和“unique: true”:

var schema = mongoose.Schema ({
    myField: { type: String, index: true, unique: true, required: true },
});

这就是您所需要的:Mongodb - Isolate sequence of operations - Perform Two Phase Commits 。但请考虑到,如果您需要进行大量事务,mongodb 可能不是最佳选择。

关于node.js - 处理 NodeJS 异步行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15692946/

相关文章:

angularjs - Mongoose: 'Cast to embedded failed for value at path. Cannot use ' in' operator to search for '_id'

javascript - 未捕获的语法错误 : await is only valid in async function in async function

ios 基于 key 创建写锁

javascript - 如何在nodejs中获取正确的时间戳值?

javascript - Node.js:http 完成事件、响应关闭事件和响应结束事件之间的区别

c# - 为什么我的记录在 mongodb upsert 场景中得到零 objectid?

javascript - 异步延迟 JS 直到满足条件

javascript - Node.js 在服务器运行时删除路由

javascript - 如何在 node.js 中将数组作为参数传递给 jar exec

node.js - MongoDb:使用唯一索引插入或更新多个文档