最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Window.unload triggers post after unload - Stack Overflow

programmeradmin2浏览0评论

I am trying to do a post to server before unloading a page and I followed this and it's working fine. My problem is the $.post on window.unload is triggered after it has unloaded. I tried it with a signout link and checking on my logs, I get the following:

Started GET "/signout" for 127.0.0.1 at 2012-11-22 00:15:08 +0800
Processing by SessionsController#destroy as HTML
Redirected to http://localhost:3000/
Completed 302 Found in 1ms


Started GET "/" for 127.0.0.1 at 2012-11-22 00:15:08 +0800
Processing by HomeController#index as HTML
  Rendered home/index.html.erb within layouts/application (0.4ms)
  Rendered layouts/_messages.html.erb (0.1ms)
Completed 200 OK in 13ms (Views: 12.9ms)


Started POST "/unloading" for 127.0.0.1 at 2012-11-22 00:15:08 +0800
Processing by HomeController#unloading as */*
  Parameters: {"p1"=>"1"}
WARNING: Can't verify CSRF token authenticity
Completed 500 Internal Server Error in 0ms

NoMethodError (undefined method `id' for nil:NilClass):
  app/controllers/home_controller.rb:43:in `unloading'

First part is the signout and then user gets redirected to root then it runs the post ('/unloading').

Is there a way to make the '/unloading' execute first then execute whatever the unload action was?

I have this as my jquery post

$(window).unload ->
  $.ajax {
    async: false,
    beforeSend: (xhr) ->
      xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
    , url: '/unloading'
    , type: 'Post'
    , data: {
      p1: '1'
    }
  }

Update

So I did transfer the ajax request to beforeunload and it was working but I had to do a return null to remove the dialog box appearing because if I don't, the ajax was still triggering on popup of dialog (even without answering "yes/no i want to leave this page"). Result is this:

window.onbeforeunload ->
  $.ajax {
    async: false,
    beforeSend: (xhr) ->
      xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
    , url: '/unloading'
    , type: 'Post'
    , data: {
      p1: '1'
    }
  }
  return null

Also, I have only tried it with Chrome for now and it's working as expected. Yet to try on other browsers.

I am trying to do a post to server before unloading a page and I followed this and it's working fine. My problem is the $.post on window.unload is triggered after it has unloaded. I tried it with a signout link and checking on my logs, I get the following:

Started GET "/signout" for 127.0.0.1 at 2012-11-22 00:15:08 +0800
Processing by SessionsController#destroy as HTML
Redirected to http://localhost:3000/
Completed 302 Found in 1ms


Started GET "/" for 127.0.0.1 at 2012-11-22 00:15:08 +0800
Processing by HomeController#index as HTML
  Rendered home/index.html.erb within layouts/application (0.4ms)
  Rendered layouts/_messages.html.erb (0.1ms)
Completed 200 OK in 13ms (Views: 12.9ms)


Started POST "/unloading" for 127.0.0.1 at 2012-11-22 00:15:08 +0800
Processing by HomeController#unloading as */*
  Parameters: {"p1"=>"1"}
WARNING: Can't verify CSRF token authenticity
Completed 500 Internal Server Error in 0ms

NoMethodError (undefined method `id' for nil:NilClass):
  app/controllers/home_controller.rb:43:in `unloading'

First part is the signout and then user gets redirected to root then it runs the post ('/unloading').

Is there a way to make the '/unloading' execute first then execute whatever the unload action was?

I have this as my jquery post

$(window).unload ->
  $.ajax {
    async: false,
    beforeSend: (xhr) ->
      xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
    , url: '/unloading'
    , type: 'Post'
    , data: {
      p1: '1'
    }
  }

Update

So I did transfer the ajax request to beforeunload and it was working but I had to do a return null to remove the dialog box appearing because if I don't, the ajax was still triggering on popup of dialog (even without answering "yes/no i want to leave this page"). Result is this:

window.onbeforeunload ->
  $.ajax {
    async: false,
    beforeSend: (xhr) ->
      xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
    , url: '/unloading'
    , type: 'Post'
    , data: {
      p1: '1'
    }
  }
  return null

Also, I have only tried it with Chrome for now and it's working as expected. Yet to try on other browsers.

Share Improve this question edited May 23, 2017 at 12:16 CommunityBot 11 silver badge asked Nov 22, 2012 at 4:58 indexindex 3,7277 gold badges40 silver badges56 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 9 +100

Try the beforeUnload event

The exact handling of the unload event has varied from version to version of browsers. For example, some versions of Firefox trigger the event when a link is followed, but not when the window is closed. In practical usage, behavior should be tested on all supported browsers, and contrasted with the proprietary beforeunload event.

  • https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload

UPDATE

The unload event is triggered when the page has unloaded.

  • https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Synchronous_and_Asynchronous_Requests#XMLHttpRequests_being_stopped

UPDATE 2

To disable the Are you sure that you want to leave this page? popup try returning null from the beforeUnload callback function

  • How to show the "Are you sure you want to navigate away from this page?" when changes committed?

UPDATE 3

Check this for cross-browser compatiblity

  • http://jonathonhill.net/2011-03-04/catching-the-javascript-beforeunload-event-the-cross-browser-way/

As @NickKnudson suggested, use the "beforeUnload" event to post back form data before the window is unloaded:

window.onbeforeunload = function() {
  $.ajax {
    async: false,
    beforeSend: (xhr) ->
      xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
    , url: '/unloading'
    , type: 'Post'
    , data: {
      p1: '1'
    }
  }
}

Ran into exact the same situation about two weeks ago, switching to beforeUnload solved the problem.

The problem is that the window's unload event does not wait for AJAX calls (which are asyncrhonous) to complete prior to closing the window. In addition, jQuery doesn't seem to have built-in handling for the beforeunload event - which is why you will need to revert to native JS code to handle this. See below:

(Note: Written in CoffeeScript)

window.onbeforeunload = function() {
    $.ajax {
        async: false, // Important - this makes this a blocking call
        beforeSend: (xhr) ->
            xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
      , url: '/unloading'
      , type: 'Post'
      , data: {
            p1: '1'
        }
    }
};

onbeforeunload - An event that fires before the unload event when the page is unloaded.

Also see this Google Forum discussion about this topic.

发布评论

评论列表(0)

  1. 暂无评论