当前位置: 首页 > 面试题库 >

处理NodeJS异步行为

万勇
2023-03-14
问题内容

将NodeJS与MongoDB + Mongoose结合使用。

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

可以说我有一个可以随时被用户调用的函数。超级“闪电般的”用户可能几乎同时调用两次。

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

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

这完全破坏了应用程序的逻辑(应查找查询,保存查询,查找查询,保存查询)。因此,我决定通过“锁定”特定用户的整个功能来防止异步行为(因此html" target="_blank">功能代码内部仍是异步的)。

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流程时是否会起作用。


问题答案:

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

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

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

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



 类似资料:
  • 本文向大家介绍Nodejs异步回调的优雅处理方法,包括了Nodejs异步回调的优雅处理方法的使用技巧和注意事项,需要的朋友参考一下 前言 Nodejs最大的亮点就在于事件驱动, 非阻塞I/O 模型,这使得Nodejs具有很强的并发处理能力,非常适合编写网络应用。在Nodejs中大部分的I/O操作几乎都是异步的,也就是我们处理I/O的操作结果基本上都需要在回调函数中处理,比如下面的这个读取文件内容的

  • 在Servlet 3.0中,引入了异步处理的概念。所以所有的书都说这消除了每个请求一个线程的要求。我已经测试过了,是的,它确实有效。现在,我有一个简单的servlet,用户在其中以同步模式启动HTTP请求。线程只需Hibernate1秒,然后回复客户端。当我对这种模式进行负载测试时,服务器每秒只能处理4个请求。现在,我将同步模式更改为异步模式,并根据请求创建一个新线程,将原始http线程释放回池。

  • 线程中使用 java.lang.Runnable 如果用户在代码中通过 java.lang.Runnable 新启动了线程或者采用了线程池去异步地处理一些业务,那么需要将 SOFATracer 日志上下文从父线程传递到子线程中去,SOFATracer 提供的 com.alipay.common.tracer.core.async.SofaTracerRunnable 默认完成了此操作,大家可以按照

  • 编写JavaScript代码时,我们要时刻牢记,JavaScript引擎是一个事件驱动的执行引擎,代码总是以单线程执行,而回调函数的执行需要等到下一个满足条件的事件出现后,才会被执行。 例如,setTimeout()函数可以传入回调函数,并在指定若干毫秒后执行: function printTime() { console.log('It is time!'); } setTimeout

  • 本文向大家介绍深入浅析NodeJs并发异步的回调处理,包括了深入浅析NodeJs并发异步的回调处理的使用技巧和注意事项,需要的朋友参考一下 这里说并发异步,并不准确,应该说连续异步。NodeJs单线程异步的特性,直接导致多个异步同时进行时,无法确定最后的执行结果来回调。举个简单的例子: 连续发起了5次读文件的异步操作,很简单,那么问题来了,我怎么确定所有异步都执行完了呢?因为要在它们都执行完后,才

  • 我正在尝试进行大量的外部服务调用,每个调用都遵循异常处理和有条件的进一步处理。我认为使用内部的. on完成来扩展这个不错的(Scala中带有期货的异步IO)示例会很容易,但似乎我对范围和/或期货有些不理解。有人能给我指出正确的方向吗? 在我的电脑上(Scala 2.10.4 ),这打印出来: 我要(顺序不重要):