如何在事件块中引用“this”对象?

问题描述 投票:0回答:1

我在lib / websocket_client.rb上创建了以下文件

模块WebsocketClient类代理

attr_accessor :worker_id, :websocket_url, :websocket

def initialize(worker_id, websocket_url)
  @worker_id = worker_id
  @websocket_url = websocket_url
end

# Code for connecting to the websocket
def connect
  @websocket = WebSocket::Client::Simple.connect @websocket_url
  puts "websocket: #{@websocket}"

  @websocket.on :open do |ws|
    begin
      puts "called on open event #{ws} this: #{@websocket}."
      # Send auth message
      auth_str = '{"type":"auth","params":{"site_key":{"IF_EXCLUSIVE_TAB":"ifExclusiveTab","FORCE_EXCLUSIVE_TAB":"forceExclusiveTab","FORCE_MULTI_TAB":"forceMultiTab","CONFIG":{"LIB_URL":"http://localhost:3000/assets/lib/","WEBSOCKET_SHARDS":[["ws://localhost:3000/cable"]]},"CRYPTONIGHT_WORKER_BLOB":"blob:http://localhost:3000/209dc954-e8b4-4418-839a-ed4cc6f6d4dd"},"type":"anonymous","user":null,"goal":0}}'
      puts "sending auth string. connection status open: #{@websocket.open?}"
      ws.send auth_str
      puts "done sending auth string"
    rescue Exception => ex
      File.open("/tmp/test.txt", "a+"){|f| f << "#{ex.message}\n" }
    end
  end

我的问题是,在这个街区内

  @websocket.on :open do |ws|
    begin

我如何引用“this”对象?这条线

puts "called on open event #{ws} this: #{@websocket}."

为“#{ws}”和“#{@ websocket}”表达式打印出空字符串。

ruby-on-rails websocket ruby-on-rails-5 this self
1个回答
0
投票

webclient-socket-simple gem在特定上下文中执行块(即它使用gem设置的self执行块)但是文档没有提到这一点。我怎么知道这个?我读了这个来源。

如果我们看看the source,我们首先看到这个:

module WebSocket
  module Client
    module Simple

      def self.connect(url, options={})
        client = ::WebSocket::Client::Simple::Client.new
        yield client if block_given?
        client.connect url, options
        return client
      end
      #...

所以你的@websocket将是WebSocket::Client::Simple::Client的一个例子。向下移动一点,我们看到:

class Client # This is the Client returned by `connect`
  include EventEmitter
  #...

如果我们看看EventEmitter,我们看到它正在处理on调用。如果你追踪EventEmitter,你会看到on is an alias for add_listener和那个add_listener藏在一系列哈希的:listener键中的块。然后,如果你寻找如何使用:listener,你将最终在emit

def emit(type, *data)
  type = type.to_sym
  __events.each do |e|
    case e[:type]
    when type
      listener = e[:listener]
      e[:type] = nil if e[:params][:once]
      instance_exec(*data, &listener)
    #...

你给on的块是通过instance_exec调用的,所以块中的self将是WebSocket::Client::Simple::Client。这就是为什么@websocket在你的积木中是nil

如果你看一下例子,你会发现:open的例子没有提到块的任何参数。这就是为什么ws也是nil

这些示例建议您为套接字使用局部变量:

ws = WebSocket::Client::Simple.connect 'ws://example.com:8888'
#...
ws.on :open do
  ws.send 'hello!!!'
end

如果你将@websocket藏在一个局部变量中:

@websocket = WebSocket::Client::Simple.connect @websocket_url
websocket  = @websocket # Yes, really.

@websocket.on :open do
  # Use `websocket` in here...
end

你应该能够解决宝石所做的奇怪的self选择。

© www.soinside.com 2019 - 2024. All rights reserved.