【问题标题】:Rails - on click event - how to deal with race condition between 2 Ruby methods?Rails - 点击事件 - 如何处理 2 个 Ruby 方法之间的竞争条件?
【发布时间】:2018-04-05 22:03:27
【问题描述】:

在我看来,我有一个 link_to 元素“开始测验!”它调用一个控制器方法(方法 A),该方法设置一个变量“Phase”并将用户重定向到一个新的静态页面。在我的 CoffeeScript 中,我有一个事件监听器来监听这个 link_to 元素的点击。监听器在后端调用不同的方法(方法 B),它使用“Phase”变量来做某事。

问题:有时方法 B 在控制器方法 A 更新之前尝试使用“相位”变量!有没有人建议最好的方法是确保在将“阶段”变量用于其他任何事情之前对其进行更新?

我是 Rails 初学者,希望得到任何指点。 :)


编辑: “阶段”是我用来跟踪测验当前问题的变量。它不依赖于任何输入,但每当呈现新页面(由单击按钮触发)时,它都需要递增。


编辑2: 我现在尝试通过向我的控制器引入实例变量标志“is_changed”并让方法 B 休眠直到标志设置为 true 来解决这个问题:

#method B:
def send_answers
   until controller.index_changed?
     sleep(0.5)
   end
   ...
   do sth.
end

#method A (in controller):
def initialize
   @index_changed = false
end

def index_changed?
   @index_changed
end

def set_index_changed!
   @index_changed = false
end

def switch_to_next_question
   ...
   self.phase += 1
   if self.save
      Thread.new do
         @index_changed = true
         ActiveRecord::Base.connection.close
      end
   else
      ...
   end
end

它不工作。方法 A 陷入睡眠。我该如何解决?这甚至是正确的方法吗?

我的@index_changed 变量的范围有问题吗?我正在尝试创建一个实例变量,该变量可从类中的多个方法访问,但对此类的每个实例都是独立的。

【问题讨论】:

  • 您将变量“相位”设置为什么?可以在渲染时显式设置吗?
  • 你只需要了解javascript和ruby事件之间的区别。 Javascript 事件处理程序将首先发生并且仅发生在浏览器上。只有在向服务器发出 HTTP 请求后才会发生 ruby​​ 事件 - 实际上,rails 并不关心它是单击还是悬停,或者只要它接收到 http 请求。
  • 正是@maxpleaner。如果您希望事件侦听器捕获该信息,您需要确保您可以在控制器后端设置数据,以便在视图中呈现(您不能只将数据传递给浏览器,它必须通过视图) .为此,您基本上需要输出数据以确保您的html视图可以输出所需的信息。
  • @max :是的,这是有道理的。但是我的 CoffeeScript 调用的方法其实是在服务器端(ActionCable 对应channel.rb)。由于该按钮按下是触发新“阶段”的唯一事物(@Cyzanfar:我正在构建一个测验应用程序,因此第 1 阶段 - 显示问题,第 2 阶段 - 显示结果等)我专门寻找一种方法以避免两种方法之间的竞争条件。

标签: javascript ruby-on-rails ruby coffeescript


【解决方案1】:

好的,我通过找到一种顺序调用这 2 个方法的方法来解决它。我最终完全消除了点击监听器并直接调用 ActionCable 后端方法,这可以通过将其转换为类方法来实现:

class QuizDataChannel < ApplicationCable::Channel
  #method B:
  def self.send_answers #self. makes it a class method
    #...
    #do something with phase
  end
end

在我的控制器中:

#method A:
def switch_to_next_question
   #...
   self.phase += 1
   if self.save
      QuizDataChannel.send_answers
   else
      #...
   end
end

正如你所见,我最终摆脱了所有这些:sleep、新线程和index_changed 标志。

【讨论】:

    猜你喜欢
    • 2012-01-26
    • 2016-11-16
    • 2013-08-10
    • 1970-01-01
    • 2017-09-07
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多