【问题标题】:How to deal with SJR responses that call code the browser doesn't have yet?如何处理调用浏览器还没有的代码的 SJR 响应?
【发布时间】:2018-07-30 15:22:39
【问题描述】:

我想知道如何缓解当用户通过 AJAX 与您的网站交互时出现的问题,并且您同时部署了新版本的网站。

想象如下场景:


用户正在通过单击“下一步”按钮浏览您的帖子。这 “下一步”按钮通过 XHR 向服务器提交表单,然后服务器使用服务器生成的 Javascript 响应 (SJR) 进行响应。

SJR 呈现这个 Javascript:

// in create.js.erb renderNewPost(<%= @post.to_json %>);

renderNewPost 定义在您连接的、缩小的application.js 中,并由用户的浏览器缓存。)

此时一切正常。

现在,作为新功能的一部分,您将端点的 SJR 更改为首先记录一些内容:

// in create.js.erb logSomething("hi!"); renderNewPost(<%= @post.to_json %>);

并将函数logSomething 添加到您的application.js

用户再次单击“下一步”按钮。这一次,SJR 响应 logSomething('hi') 行...但是浏览器没有在任何地方定义 logSomething,因为浏览器加载的 application.js 是第一个版本。

现在用户将无法使用您的网站,直到页面被刷新。


我们如何解决这个问题?手头的问题有名称吗?

【问题讨论】:

  • 那么,您是在用户请求之间部署新版本吗?
  • @gasc 是的。不知道为什么这被否决:(

标签: javascript ruby-on-rails ajax


【解决方案1】:

选项 1:

一个简单的选择是,让响应尽可能独立,这意味着在您的示例中,您不会在其他地方定义 log_something 方法,但也在同一个响应中。

选项 2:

另一种可能更通用的解决方案是,您在应用程序控制器中的自定义响应标头(比如说X-SJR-Version)中发送某种版本

before_action do
  response.headers['X-SJR-Version'] = '1.0.0'
end

并添加一些 Javascript 客户端代码,您可以在其中执行 AJAX 请求以检查版本是否仍然匹配。 粗略的实现可能是这样的(未经测试):

var version = null;
$(document).bind("ajaxSuccess", function(xhr, status){
   var newVersion = xhr.getResponseHeader('X-SJR-Version')
   if(version === null) { version = newVersion } // initial version
   if(newVersion !== version) { location.reload(); }
});

这利用 jquery 钩子ajaxSuccess 来执行版本检查。如果您使用常规 jquery-ujs rails 调用,您可能需要检查 this 页面。

现代方法:

然而,现代 Rails 应用程序通常不再经常使用服务器生成的 javascript,因为那里的架构通常是自己编写客户端 javascript(通常使用 react、angular 或 vue)并使用 JSON API 端点 用于来自服务器的数据,而 javascript 代码已经存在于页面的响应中,不需要加载额外的 JS。

这样做的好处是,您可以使用 API-Versioning,而加载的 javascript 将坚持旧版本,因此您可以顺利转换到更新的 API 版本(虽然通常您甚至不需要新的 API 版本,因为只有 javascript 发生变化)

因此,您很可能找不到针对此问题的开箱即用解决方案,而不得不采用上述方法。

【讨论】:

    猜你喜欢
    • 2018-04-23
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    • 2015-11-05
    • 1970-01-01
    • 2017-09-05
    • 1970-01-01
    • 2018-10-28
    相关资源
    最近更新 更多