9

假设我有一个带有帖子的博客应用程序。创建帖子后,会创建一个工作人员来处理一些后台操作。我的情况是,在提交帖子表单后,我想显示某种加载消息(gif 加载器等),当工作人员完成时,我想隐藏加载消息并显示工作人员提供的一些数据。我的问题是传达工作人员已完成工作并将其显示在用户前端的最佳方式是什么。工人回调看起来像这样

def worker_finish
  #message the user
end
4

1 回答 1

13

我认为你可能错过了拥有后台工作人员的意义,基本上,你试图做的是自我挫败。-- 如果用户提交表单并且您在控制器中排队作业,只是为了让用户等待工作人员开始和完成,您不仅完全完成了控制器本身可以完成的事情,而且您已经完成了使过程变得更加复杂(并且这种类型的功能没有内置到 resque 或 sidekiq 中)。

当卸载要由队列处理的作业时,您希望立即向客户端返回响应,即

class PostsController < ApplicationController
  def create
    @post = Post.create(params[:post])
    BackgroundBlogOperation.enque(@post.id)
    respond_with(@post)
  end
end

然后将 BackgroundBlogOperation 类放入队列中,供工作人员通过并完成工作。如果您需要 BackgroundBlogOperation 工作人员在完成后执行其他操作,您可以这样做,但这应该发生在工作本身内,以便工作人员可以负责。

如果您只是在创建帖子后尝试显示和隐藏微调器,而不重新加载页面,只需在单击提交按钮之前显示 javascript 微调器,并确保请求类型为 js(添加 :remote => true 到表单)。然后创建一个 javascript 视图响应,如下所示:

class PostsController < ApplicationController
  respond_to :js, :only => [:create]
  def create
    @post = Post.create(params[:post])
    BackgroundBlogOperation.enque(@post.id)
    respond_with(@post)
  end
end

create.js.erb 还可以附加一条消息,告诉他们您在后台执行的任何操作都已排队,如果它比创建帖子或其他内容更复杂的话。

$("#spinner").hide();

现在——虽然你最初问的内容没有任何用途(因为在工作完成时显示和隐藏微调器需要等待控制器完成操作)——在某些情况下向客户端显示该工作已完成处理很有用。

首先让我们定义一个后台处理实际有用的场景。假设您有一个按钮,当单击该按钮时,它将从某个外部 api 中提取数据,并且在从外部站点获取数据后,您正在根据响应执行数据库操作。这将是何时使用后台进程的一个很好的例子。基本上在控制器中,您会执行以下操作:

class ApiController < ApplicationController
  respond_to :js, :only => [:create]

  def sync_tweets
    TwitterApiJob.enque(current_user.twitter_username)
    respond_with(message: 'Syncing Tweets')
  end

end

现在,告诉用户推文何时完成同步有点复杂,您有 3 个基本选项:

1) 通过电子邮件通知用户(通常是最差的选项 imo) 2) 使用某种 html5 或支持 websocket 的 rails 服务器来运行 rails,并通过 websocket 向客户端发送推送,这虽然很酷,但在大多数情况下是矫枉过正和超出本回复范围。如果您想查看您的选项,Google 会跟踪 websocket 推送。3)在大多数情况下,IMO 最佳选择,创建一个通知模型来处理各种用户通知,并在您的工作中,在工作完成后,执行类似的操作

Notification.create(:user_id => user.id, :message => 'Sync has finished', type => 'sync_complete')

然后,用户请求的下一页,在标题工具栏或任何地方,我会注意到用户有未读通知,以提醒用户点击它。

---我也认为在您的帖子中您提到您正在使用resque。我尝试了 resque,它很不错,但我发现它在生产中调试过于复杂,而且它使用了疯狂的内存——如果你还没有的话,我建议你检查一下 sidekiq,它也使用 redis,但使用起来要快得多线程:

https://github.com/mperham/sidekiq

恕我直言,它更快、更干净、更容易设置。

于 2012-11-15T06:30:52.957 回答