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

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

问题描述

将NodeJS与MongoDB + Mongoose结合使用.

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

当然它是这样执行的:查找查询,查找查询,保存查询,保存查询

Of course it executes like this: FIND QUERY, FIND QUERY, SAVE 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
    }
}

所以,我的问题是:这是一种好习惯,好技巧还是坏技巧?如果是骇客,请提供其他解决方案.尤其是,我怀疑这种解决方案在我们扩展和启动多个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().另一种解决方案是使用索引.当您尝试两次保存相同的字段时,您将收到一个错误.在猫鼬的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天全站免登陆