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

时间:2018-04-02 19:43:16

标签: ruby-on-rails websocket ruby-on-rails-5 this self

我在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}”表达式的空字符串。

1 个答案:

答案 0 :(得分: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)
    #...

您通过instance_exec调用on提供的阻止,因此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

你应该能够解决宝石所做的奇怪的#include<iostream> using namespace std; int main() { int k[11]; int i, a, n, s; for (a = 2; a <= 1000; a++) { n = 0; s = a; for (i = 1; i < a; i++) if (a%i == 0) { n++; s = s - i; k[n] = i; } if (s == 0) { cout << a << " is a perfect number" << endl; cout << "its factors are:"; for (i = 1; i <= n; i++)cout << k[i] << " "; cout << endl; } } return 0; } 选择。