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

javascript - 'onbeforeunload' Fires Twice - Stack Overflow

programmeradmin6浏览0评论

I want to send an ajax request when a user leaves a page or closes the window.
Here is my code inside :

<script type="text/javascript">
    function sendajax(){
        $.ajax({
          url: "someurl",
          data: mydata,
          async : false
        });   
    }
</script>
    <script type="text/javascript">
     window.onbeforeunload=function(){sendajax();};
</script>   

When the event occurs the event fires twice.
Why does in happen?
I know I can prevent it by adding a variable var ajaxSent=true; but may be there is a cleaner way to do it?

UPD:
I replaced the sendajax function content with some other code (without sending ajax) and found out that ajax is not the one causing the problem. It still enters the function twice.

I want to send an ajax request when a user leaves a page or closes the window.
Here is my code inside :

<script type="text/javascript">
    function sendajax(){
        $.ajax({
          url: "someurl",
          data: mydata,
          async : false
        });   
    }
</script>
    <script type="text/javascript">
     window.onbeforeunload=function(){sendajax();};
</script>   

When the event occurs the event fires twice.
Why does in happen?
I know I can prevent it by adding a variable var ajaxSent=true; but may be there is a cleaner way to do it?

UPD:
I replaced the sendajax function content with some other code (without sending ajax) and found out that ajax is not the one causing the problem. It still enters the function twice.

Share Improve this question edited Feb 15, 2020 at 9:05 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Jan 3, 2012 at 11:10 lvillvil 4,3369 gold badges51 silver badges78 bronze badges 7
  • Are there any iframes on the page? – beeglebug Commented Jan 3, 2012 at 11:22
  • No, this is a a part of a test page that has only some text and a link – lvil Commented Jan 3, 2012 at 11:27
  • Can you provide an example? Also, what browser are you seeing this happen in? – beeglebug Commented Jan 4, 2012 at 8:30
  • this is the only code after the head tag: '<body> sssssss <a href="www.ww">abc</a> </body>' I've tried it in Chrome16 and Firefox3.6 both on Ubuntu – lvil Commented Jan 4, 2012 at 8:42
  • 1 Odd, I can't get the event to fire multiple time on my Windows 7 machine in any browser. If you try this jsFiddle that mimics your code: jsfiddle/rWKdR does it happen twice? – beeglebug Commented Jan 4, 2012 at 8:58
 |  Show 2 more ments

6 Answers 6

Reset to default 6

Based on the code in your edit and ments, it looks like it could simply be caused by the broken link you are clicking to leave the page.

Given the following code:

<script>
    function doSomething() { console.log('onbeforeunload fired'); }
    window.onbeforeunload = doSomething;
</script>
<a href="garbage">link A</a>
<a href="http://google.">link B</a>

If I click on link A, I get two console log entries, if I click on link B I only get one.

It looks like it could be a quirk of how the browsers handle their internal "This web page has not been found" pages, causing your page to be refreshed and closed again before showing the message, leaving you with two occurrences of the onbeforeunload event.

I had the same problem and it took a while to understand and resolve, sharing the case details:

There was a custom JS within our template that manipulated the menu. It caused the unload to fire twice, only when clicking on the menu links, not on other links, and only in IE/EDGE.

We eventually stopped the propagation on these links and the problem was resolved.

$('.SELECTOR a[href^="http://"]').on('click', function(e){
    e.stopPropagation();
});

It's a specific bug in your application, therefore you won't find too much information on google.

In React/Next js, I also encounter same issue. my beforeunload event fire 3-4 times. I just solve this issue by adding a removeEventListener.

Now its fire only 1 time.

useEffect(() => {
        console.log("zzzzzzzzzzzzz 003 ",formLoadingState)

        const handleBeforeUnload = (event) => {
            console.log("zzzzzzzzzzzzz 033 ",formLoadingState)

            if (formLoadingState) {
                event.preventDefault()
                event.returnValue = ''
            }
        }
        
        window.addEventListener('beforeunload', handleBeforeUnload)
        return () => {
            window.removeEventListener('beforeunload', handleBeforeUnload)
        }
    }, [formLoadingState])

You could try the following code:

<script type="text/javascript"><br>
     window.onbeforeunload=function sendajax(){<br>
        $.ajax({<br>
          url: "someurl",<br>
          data: mydata,<br>
          async : false<br>
        });<br>
};<br>
</script>

or you can define sendajax() {} at some place and the use it like onbeforeunload = "sendajax()" not as onbeforeunload = "function () { sendajax() }"

beforeUnload is cancellable

I know this post is quite old but from the Chrome Pagelifecycle API documentation, browsers can occasionally partially unload pages to save resources. https://developers.google./web/updates/2018/07/page-lifecycle-api beforeUnload is not reliable to make sure that the page is closed. This especially happens on android devices when the screen is locked.

There is a jsfiddle that I found somebody wrote that you can test out https://jsfiddle/ov6b9pdL/. Keep the screen locked for 5-10 minutes on Chrome android and you'll see that beforeUnload is fired without even closing the tab.

$(document).ready(function() {
    window.addEventListener('beforeunload', showLoader);
});

var showLoader = function() {
    $('#loader').show();
};

Agree with AlonMichaeli's concept. In my application there was anchor tag wrapped with in a div together with couple of spans. When Anchor was clicked on a dirty page, there was couple of 'Leave site' notifications. It worked fine if any other part of menuItem (div or spans) are clicked. So in custom javascript method I've added stopped propagation and preventDefault only if anchor tag is clicked. Somehow in this case preventDefault is necessary.

function menuItemClicked(event: JQueryEventObject) {
  var item = $(event.target);
  if (item.is(".anchor-item")) { 
    event.stopPropagation();
    event.preventDefault();
  }
  href = item.closest(".anchor-item").attr("href");
  if (!event.ctrlKey && href) {
    window.location.href = href;
  }
}
发布评论

评论列表(0)

  1. 暂无评论