首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用BubbleWrap进行RubyMotion异步编程

使用BubbleWrap进行RubyMotion异步编程
EN

Stack Overflow用户
提问于 2012-11-01 04:57:28
回答 3查看 1.6K关注 0票数 2

在使用大量异步代码时,我对如何编写像样的代码感到困惑。

在下面的代码片段中,我登录以获取身份验证cookie,并在下一个请求中使用该cookie来获取项目名称的列表(作为示例):

代码语言:javascript
复制
def self.populateProjectsTable(projects_controller)
  payload = {email: "email", password: "pass"}
  HTTP.post("http://example.com/login", {payload: payload}) do |response|
    authCookie = response.headers['Set-Cookie']
    HTTP.get("http://example.com/projects.json", {cookie: authCookie}) do |response|
      projects = JSON.parse(response.body.to_str)
      projects_controller.projects = projects
      projects_controller.reloadData
    end
  end
end

虽然这会起作用,但代码感觉很脏。没有真正遵循单一责任原则。我想用几种方法来提取它:

代码语言:javascript
复制
def self.populateProjectsTable(projects_controller)
  @taskList = TaskList.new
  @taskList.doLogin
  projects = @taskList.getProjects
  projects_controller.projects = projects
  projects_controller.reloadData
end

def doLogin
  payload = {email: "email", password: "pass"}
  HTTP.post("http://example.com/login", {payload: payload}) do |response|
    @authCookie = response.headers['Set-Cookie']
  end
end

def getProjects
  HTTP.get("http://example.com/projects.json", {cookie: @authCookie}) do |response|
    projects = JSON.parse(response.body.to_str)
  end
end

这显然行不通。getProjects方法是在doLogin完成之前调用的,项目仅在块的作用域中已知,不会将数据返回给populateProjectsTable方法。

如果没有第一个示例中所示的嵌套,如何编写这样的应用程序?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-01 05:46:44

你不会完全脱离嵌套的。接受Alan的答案,并对其进行一些调整,这就是我想出来的。它涉及到通过几个方法传递一个块。

代码语言:javascript
复制
def self.populateProjectsTable(projects_controller)
  @taskList = TaskList.new
  @taskList.loginAndGetProjects do |projects|
    projects_controller.projects = projects
    projects_controller.reloadData
  end
end

def loginAndGetProjects(&block)
  payload = {email: "email", password: "pass"}
  HTTP.post("http://example.com/login", {payload: payload}) do |response|
    @authCookie = response.headers['Set-Cookie']
    getProjects(&block)
  end
end

def getProjects(&block)
  HTTP.get("http://example.com/projects.json", {cookie: @authCookie}) do |response|
    projects = JSON.parse(response.body.to_str)
    block.call(projects)
  end
end
票数 4
EN

Stack Overflow用户

发布于 2012-11-01 09:25:03

我也遇到过类似的问题,试图包装本身需要块的方法。我希望新的包装器方法仍然能够接受块。下面是我在ParseModel中做的事情

代码语言:javascript
复制
# with block:
# ParseModel::Cloud.callFunction("myFunction", {"myParam" => "myValue"}) do |result, error|
#  # do something...
# end

# without block:
# ParseModel::Cloud.callFunction("myFunction", {"myParam" => "myValue"})
module ParseModel
  class Cloud
    def self.callFunction(function, params={}, &block)
      return PFCloud.callFunction(function, withParameters:params) unless block_given?

      PFCloud.callFunctionInBackground(function, withParameters:params, block:lambda do |result, error|
        block.call(result, error)
      end)
    end
  end
end

将这个概念应用到您的问题中,您可以重写您的方法以获取块本身。这里有一点重构,我认为这可能会有帮助:

代码语言:javascript
复制
def self.populateProjectsTable(projects_controller)
  @taskList = TaskList.new
  @taskList.doLogin do |login_response|
    authCookie = login_response.headers['Set-Cookie']
    @taskList.getProjects(authCookie) do |projects_response|
      projects = JSON.parse(projects_response.body.to_str)
      projects_controller.projects = projects
      projects_controller.reloadData
    end
  end
end

def doLogin(&block)
  payload = {email: "email", password: "pass"}
  HTTP.post("http://example.com/login", {payload: payload}) do |response|
    block.call(response)
  end
end

def getProjects(cookie, &block)
  HTTP.get("http://example.com/projects.json", {cookie: cookie}) do |response|
    block.call(response)
  end
end

我不认为你已经完全摆脱了SRP的困境,但这应该是一个很好的开始。

票数 4
EN

Stack Overflow用户

发布于 2012-12-01 06:51:35

Jamon的答案是+1。

如果您喜欢SRP,我可能建议使用一个类来管理您的会话,并将API拆分到一个模块中。这在您添加额外的API调用时特别有用。在这里,我排队请求,这些请求将在登录完成后得到满足。稍后,您可以添加对超时等的处理。

代码语言:javascript
复制
module ProjectApi
  def get_projects(&block)
    with_session do
      HTTP.get("http://example.com/projects.json", {cookie: @auth_cookie}) do |response|
        projects = JSON.parse(response.body.to_str)
        block.call(projects)
      end
    end
  end
end

class MySession
  include ProjectApi

  def initialize(login, password)
    @login = login
    @password = password
    @state = nil
    @requests = []
  end

  def active?
    @state == :active
  end

  def with_session(&block)
    @requests << &block
    active? ? handle_requests : login(true)
  end

  private

  def login(do_handle_requests = false)
    payload = {login: @login, password: @password}
    @state = nil
    HTTP.post("http://example.com/login", {payload: payload}) do |response|
      @state = :active
      @auth_cookie = response.headers['Set-Cookie']}
      handle_requests if do_handle_requests
    end
  end  

  def handle_requests
    while request = @requests.shift do
      request.call
    end if active?
  end    

end

def self.populateProjectsTable(projects_controller)
  @session ||= MySession.new('mylogin', 'mypassword')
  @session.get_projects do |projects|
    projects_controller.projects = projects
    projects_controller.reloadData
  end
end
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13167304

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档