新手问题 ajax delete 请求后页面不刷新

Awlter1 · 2018年10月24日 · 最后由 Awlter1 回复于 2019年01月16日 · 2210 次阅读

最开始,我用 ajax 发送了一个 delete 请求,遇到了这个问题

在 destroy action 中 redirect_to 到一个 index 页面,rails 用了 delete 请求而不是 get

google 了一下,说用 status: 303

https://makandracards.com/makandra/38347-redirecting-responses-for-patch-or-delete-will-not-redirect-with-get

带上 303 之后,看 server 确实是用的 get, 也不报错了,该 render 的都 render 了,可就是不刷新页面

请问这是为什么鸭


上代码和日志:

edit.js.erb

$('#confirm_button').click(function() {
  var url = $('.js-submit-delete-section').data('url')

  $.ajax({
    method: 'delete',
    url: url,
  })
})

现在 workable 的代码

def destroy
  @section.destroy

  ...
  flash[:notice] = "删除成功"
  render js: "window.location = '#{course_sections_path(@course)}'"
end

log

Started DELETE "/courses/5b582404421aa97728ee4e2f/sections/5b681976421aa9c55b549830" for 127.0.0.1 at 2018-10-25 20:49:56 +0800
Processing by Courses::SectionsController#destroy as */*
....
Started GET "/courses/5b582404421aa97728ee4e2f/sections" for 127.0.0.1 at 2018-10-25 20:49:56 +0800
Processing by Courses::SectionsController#index as HTML

最开始有问题的代码

controller

def destroy
  @section.destroy

  if params[:destroy_content] && @section.content.destroy
    flash[:success] = "成功解绑并删除"
  end

  if params[:unbind_course_from_content] && @section.content.update(course: nil)
    flash[:success] = "成功解绑并转换为直播"
  end

  flash[:notice] = "删除成功"
  redirect_to action: :index
end

log

Started DELETE "/courses/5b582404421aa97728ee4e2f/sections/5b681970421aa9c55b54982e" for 127.0.0.1 at 2018-10-25 20:51:16 +0800
Processing by Courses::SectionsController#destroy as */*
  Parameters: {"course_id"=>"5b582404421aa97728ee4e2f", "id"=>"5b681970421aa9c55b54982e"}
MONGODB | localhost:27017 | MagNet_development.find | STARTED | {"find"=>"users", "filter"=>{"_id"=>BSON::ObjectId('56a8b4c9feec620985000000')}, "limit"=>1, "
MONGODB | localhost:27017 | MagNet_development.update | SUCCEEDED | 0.0023810000000000003s
Redirected to http://localhost:3000/courses/5b582404421aa97728ee4e2f/sections
Completed 302 Found in 78ms


Started DELETE "/courses/5b582404421aa97728ee4e2f/sections" for 127.0.0.1 at 2018-10-25 20:51:16 +0800

ActionController::RoutingError (No route matches [DELETE] "/courses/5b582404421aa97728ee4e2f/sections"):
  actionpack (4.2.5) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
  actionpack (4.2.5) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
.....

尝试用 303 解决后,但是页面不刷新

controller

def destroy
    @section.destroy

    if params[:destroy_content] && @section.content.destroy
      flash[:success] = "成功解绑并删除"
    end

    if params[:unbind_course_from_content] && @section.content.update(course: nil)
      flash[:success] = "成功解绑并转换为直播"
    end

    flash[:notice] = "删除成功"
    redirect_to action: :index, status: 303
  end

log

Started DELETE "/courses/5b582404421aa97728ee4e2f/sections/5bd1bc8aa33259a591f0a71d" for 127.0.0.1 at 2018-10-25 20:52:33 +0800
Processing by Courses::SectionsController#destroy as */*
  Parameters: {"course_id"=>"5b582404421aa97728ee4e2f", "id"=>"5bd1bc8aa33259a591f0a71d"}
MONGODB | localhost:27017 | MagNet_development.find | STARTED | {"find"=>"users", "filter"=>{"_id"=>BSON::ObjectId('56a8b4c9feec620985000000')}, "limit"=>1, 
MONGODB | localhost:27017 | MagNet_development.update | SUCCEEDED | 0.0015010000000000002s
Redirected to http://localhost:3000/courses/5b582404421aa97728ee4e2f/sections
Completed 303 See Other in 45ms


Started GET "/courses/5b582404421aa97728ee4e2f/sections" for 127.0.0.1 at 2018-10-25 20:52:33 +0800
Processing by Courses::SectionsController#index as */*
  Parameters: {"course_id"=>"5b582404421aa97728ee4e2f"}
MONGODB | localhost:27017 | MagNet_development.find | STARTED | {"find"=>"users", "filter"=>{"_id"=>BSON::ObjectId('56a8b4c9feec620985000000')}, "limit"=>1, 
  Rendered layouts/admin/_main_sidebar.html.slim (100.1ms)
  Rendered layouts/admin/_flash_messages.html.slim (4.7ms)
  Rendered layouts/admin/_main_footer.html.slim (3.0ms)
Completed 200 OK in 1147ms (Views: 1120.4ms)
Awlter1 关闭了讨论。 10月24日 20:50
Awlter1 重新开启了讨论。 10月24日 21:14

我的经验是 ajax 的重定向应该

render js: 'window.location.href=xxxxx'
zhuoerri 回复

谢谢,我也看到重新定向那块了,https://stackoverflow.com/questions/46778581/redirection-to-a-get-after-a-put-in-rails-status-303-not-working,我研究下。

我以为我设置了 format,之后就跟 ajax 没关了

redirect_to xx_path(@course, format: :html), status: :see_other

Awlter1 关闭了讨论。 10月24日 21:56
Awlter1 重新开启了讨论。 10月24日 22:21

你这个是没有路由到 delete rails 对 http delete 识别是通过在请求参数中加入一个 patch 实现的来着

zouyu 回复

hmm, 没太明白的你意思,有相关文章推荐下吗?

确实是 route 到 destroy action 了,只是在 destroy action 中 redirect_to :index 时出现的问题

Awlter1 回复

你发的截图提示没找到路由

zouyu 回复

能重新看一遍帖子吗兄得,我 google 解决了那个找不到路由的问题了。我的帖子问的是另外一个问题

redirect_to :index ? 不应该是这样吗 redirect_to action: 'index'

hiveer 回复

你说得对,我这里就是想表达跳转的 index 页面。项目里不是这么写的

日志显示就是没找到路由,你以为的问题可能和实际问题不一样,把代码和意图贴上来。

重定向是浏览器才有权利做的事情,服务端只能作出指示。

如果是普通请求,浏览器收到服务端重定向 (3xx 状态码) 的指示后,会自动再向指示的地址发送一个请求,达到页面刷新。

如果变成了 AJAX 请求,浏览器是不会响应重定向状态码指示的,这时候可以用 #3 上面说的方法,渲染一段 JS 代码给浏览器,浏览器收到后会执行实现页面刷新

Awlter1 回复

日志显示没有 route 到 destroy action。

Rei 回复

咱俩都看错这个帖子的意思了,楼主这个帖子是图片中的问题解决了。但是遇到了另外一个问题

如果是手工发 ajax 请求,要自己处理浏览器返回的内容。所以还是:上代码。

你这个问题涉及的知识,值得分享下: 用 303 的原因是,默认的 302 或者 301(永久跳转)是不会改变请求方法的,也就是你在发送 DELETE 请求的时候,如果是 DELETE,那么跳转的时候还是会用 DELETE,但是如果你想跳的是个页面那么明显需要用 GET。这时候就需要用 303,303 就是为此而生。refer: https://zh.wikipedia.org/wiki/HTTP_303

再说没刷新的问题:
前端发送的请求有两种方式,浏览器发送或者 JS 发送。是浏览器发送的话,默认是会在新页面给你渲染的,所以肯定会刷新,即便你没有 redirect,只是 render。
如果是 JS 发送的话,因为是异步的,所以是不会自己去刷新页面的,就需要你自己去刷新,通过更改 window.location.href

Rei 回复

神说这个帖子要上代码,于是便有了代码

hiveer 回复

十分感谢🙏解释的真清晰!

pinewong 回复

谢谢你,我看明白啦!

顺着你的思路我想能不能把 ajax 伪装成一个普通的请求。。查了下好像不行

https://stackoverflow.com/questions/6432320/how-to-make-an-ajax-request-look-like-a-regular-normal-request

AJAX 请求不会导致影响页面本身的。你的 AJAX 应该返回处理的结果(成功或失败),返回一个 JSON 的话就是比如说 {"error": 0, "redirect": "/"} 这样,然后你自己再写一个回调函数处理结果,比如根据 error 和 redirect 的值,执行对应的跳转代码。

不应该是重新是 format 到 js.rb 文件,然后渲染部分更改内容么

Awlter1 回复

你这个伪装骗过了服务器,但没有骗过浏览器,浏览器还是当成 AJAX 请求处理

这个问题最近又出现了,貌似

format.js { render js: "window.location = '#{course_sections_path(@course)}'" }

不管用了

ActionController::RoutingError (No route matches [DELETE] "/courses/5c122c196799f367fb742aa8/sections"):
  actionpack (4.2.5) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
  actionpack (4.2.5) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
  lograge (0.7.1) lib/lograge/rails_ext/rack/logger.rb:15:in `call_app'
  railties (4.2.5) lib/rails/rack/logger.rb:20:in `block in call'
  activesupport (4.2.5) lib/active_support/tagged_logging.rb:68:in `block in tagged'
  activesupport (4.2.5) lib/active_support/tagged_logging.rb:26:in `tagged'
  activesupport (4.2.5) lib/active_support/tagged_logging.rb:68:in `tagged'
  railties (4.2.5) lib/rails/rack/logger.rb:20:in `call'
  quiet_assets (1.1.0) lib/quiet_assets.rb:27:in `call_with_quiet_assets'
  request_store (1.3.2) lib/request_store/middleware.rb:9:in `call'
  actionpack (4.2.5) lib/action_dispatch/middleware/request_id.rb:21:in `call'
  rack (1.6.10) lib/rack/methodoverride.rb:22:in `call'
  rack (1.6.10) lib/rack/runtime.rb:18:in `call'
  activesupport (4.2.5) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
  rack (1.6.10) lib/rack/lock.rb:17:in `call'
  actionpack (4.2.5) lib/action_dispatch/middleware/static.rb:116:in `call'
  rack (1.6.10) lib/rack/sendfile.rb:113:in `call'
  sentry-raven (2.7.3) lib/raven/integrations/rack.rb:51:in `call'
  railties (4.2.5) lib/rails/engine.rb:518:in `call'
  railties (4.2.5) lib/rails/application.rb:165:in `call'
  rack (1.6.10) lib/rack/content_length.rb:15:in `call'
  thin (1.7.2) lib/thin/connection.rb:86:in `block in pre_process'
  thin (1.7.2) lib/thin/connection.rb:84:in `catch'
  thin (1.7.2) lib/thin/connection.rb:84:in `pre_process'
  thin (1.7.2) lib/thin/connection.rb:53:in `process'
  thin (1.7.2) lib/thin/connection.rb:39:in `receive_data'
  eventmachine (1.2.5) lib/eventmachine.rb:194:in `run_machine'
  eventmachine (1.2.5) lib/eventmachine.rb:194:in `run'
  thin (1.7.2) lib/thin/backends/base.rb:73:in `start'
  thin (1.7.2) lib/thin/server.rb:162:in `start'
  rack (1.6.10) lib/rack/handler/thin.rb:19:in `run'
  rack (1.6.10) lib/rack/server.rb:287:in `start'
  railties (4.2.5) lib/rails/commands/server.rb:80:in `start'
  railties (4.2.5) lib/rails/commands/commands_tasks.rb:80:in `block in server'
  railties (4.2.5) lib/rails/commands/commands_tasks.rb:75:in `tap'
  railties (4.2.5) lib/rails/commands/commands_tasks.rb:75:in `server'
  railties (4.2.5) lib/rails/commands/commands_tasks.rb:39:in `run_command!'
  railties (4.2.5) lib/rails/commands.rb:17:in `<top (required)>'
  bin/rails:9:in `require'
  bin/rails:9:in `<top (required)>'
  spring (2.0.2) lib/spring/client/rails.rb:28:in `load'
  spring (2.0.2) lib/spring/client/rails.rb:28:in `call'
  spring (2.0.2) lib/spring/client/command.rb:7:in `call'
  spring (2.0.2) lib/spring/client.rb:30:in `run'
  spring (2.0.2) bin/spring:49:in `<top (required)>'
  spring (2.0.2) lib/spring/binstub.rb:31:in `load'
  spring (2.0.2) lib/spring/binstub.rb:31:in `<top (required)>'
  bin/spring:13:in `require'
  bin/spring:13:in `<top (required)>'
  bin/rails:3:in `load'
  bin/rails:3:in `<main>'
Awlter1 关闭了讨论。 01月16日 16:30
Awlter1 重新开启了讨论。 01月16日 16:30

新问题没法置顶是吧。。

Awlter1 又是关于 ajax 的问题 提及了此话题。 01月16日 16:31
需要 登录 后方可回复, 如果你还没有账号请 注册新账号