处理 NodeJS 异步行为 [英] Dealing with NodeJS asynchronous behavior

查看:51
本文介绍了处理 NodeJS 异步行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 MongoDB+Mongoose 中使用 NodeJS.

Using NodeJS with MongoDB+Mongoose.

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

First of all, I know the advantages of async non-blocking code. So I do deal with callbacks. But finally I faced the following problem.

假设我有一个用户可以随时调用的函数.并且有可能,一个超级闪电般"的用户几乎同时调用两次.

Lets say I have a function which can be called by user any time. And it is possible, that a super "lightning-speed" user call it twice almost at the same time.

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

Of course it executes like this: FIND QUERY, FIND QUERY, SAVE QUERY, SAVE QUERY

这完全打破了应用程序的逻辑(应该 FIND QUERY、SAVE QUERY、FIND QUERY、SAVE QUERY).所以我决定通过为特定用户锁定"整个函数来防止异步行为(因此函数代码内部仍然是异步的).

This totally breaks the logic of an app (should FIND QUERY, SAVE QUERY, FIND QUERY, SAVE QUERY). So I decided to prevent asynchronous behavior by "locking" the whole function for particular user (so inside the function code is still async).

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
    }
}

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

So, my question is: is it a good practice, good hack or bad hack? If it is a bad hack, please provide any other solution. Especially, I doubt this solution will work when we scale and launch more than one NodeJS processes.

推荐答案

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

This is a very bad practice, you should never use timers to control the flow of the code.

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

The problem here is called atomicity. If you need to do find-save, find-save then you need to pack these operations somehow (transaction). It depends on the software you use. In redis you have the multi and exec commands. In mongodb you have findAndModify(). Another solution is to use an index. When you try to save the same field twice you get an error. Use the attributes, "index: true" and "unique: true" in the schemaType in mongoose:

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

这就是你需要的:Mongodb - 隔离操作序列 -执行两阶段提交.但是要考虑到,如果您需要进行大量交易,mongodb 可能不是最佳选择.

This is what you need: Mongodb - Isolate sequence of operations - Perform Two Phase Commits. But take into account that mongodb could not be the best choice if you need to do a lot of transactions.

这篇关于处理 NodeJS 异步行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆