Synchronous Ajax - does Chrome have a timeout on trusted events?

后端 未结 3 1734
忘了有多久
忘了有多久 2021-02-05 13:25

Situation

We have a situation, where we need to onclick-open a new tab in browsers after performing an XHR / Ajax request.

We do this by setti

相关标签:
3条回答
  • 2021-02-05 13:45

    Hello @ChristopherLörken. Can you give a example code or a fiddle of what are you doing? Maybe I'm not understanding what you want.

    I think this will help:
    If you need the event in your context, you can save the reference of the event for posterior use, like in a callback. Example using jQuery:

    $(myBtn).click(function(ev){
       var event = ev; //Save the event object reference
       $.ajax({
       // ... your options
       success: function(res){
         //do stuff with the event in the callback
         console.log(event);
       });
    });
    

    In this way, you don't need call a sync request to use the event in your context and, as a async request, chrome don't complain with that. :)

    0 讨论(0)
  • 2021-02-05 14:11

    What might fix this is opening the new tab before the XHR request returns and while you are still in the trusted context. Browser tabs and windows opened via Javascript maintain connections with the parent window and can communicate back and forth.

    If you open a new tab when a link is clicked, you can show a loading screen in the new window while the XHR call runs. This workflow isn't quite as clean as your original request, but it would be a viable solution with some thought. The script below is just a quick example using window.setTimeout() to simulate an async XHR request.

    <html>
    <body>
        <h4>
        Hello
        </h4>
        <a id="openWindow" href="">Make http call and open window.</a>
    
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
        <script>
            (function ($) {
                var newWindow = null,
                    timeout = null;
    
              $(document).ready(function () {
                $('#openWindow').on('click', function (evt) {
                    evt.preventDefault();
    
                  newWindow = window.open('about:blank', 'tempWindow');
                  $(newWindow.document).find('body').append('<div class="loading">Loading...</div>');
    
                  timeout = window.setTimeout(function () {
                    // simulates async XHR
                    $(newWindow.document).find('.loading').remove();
                    $(newWindow.document).find('body').append('Done loading, here\'s your data');
    
                  }, 5000)
    
                });
              });
    
            }(jQuery));
        </script>
    </body>
    

    0 讨论(0)
  • 2021-02-05 14:11

    Your problem is not with XMLHttpRequest, but with delay (sync delay, maybe bug in WebKit/Blink)

    See example (http://jsfiddle.net/23JNw/32/ sandbox in Snippet don't allow pop-ups):

    function performSlowSyncronousRequest() {
        var endsIn, initial;
    
        delay = 5000;
    
        endsIn = new Date().getTime() + delay;
    
        for (; endsIn >= new Date().getTime();) {}//Delay
        window.open('http://www.thirtykingdoms.com');
    }
    
    <button onclick="performSlowSyncronousRequest()">Test case</button>
    

    Note: that sjax (XMLHttpRequest sync) is considered obsolete by some browsers is very bad for the user experience.

    I tried simulate click, but not work:

    function clickFire(evt){
    	var el, evtFake, pos;
    
    	el = document.createElement("a");
        el.href = "javascript:void(0);";
        el.innerHTML = "test";
    	el.onclick = evt;
    
    	document.body.appendChild(el);
    
    	pos = el.getBoundingClientRect();
    
    	evtFake = new MouseEvent("click", {
    		bubbles: false,	
    		cancelable: false,
    		view: window,
    		detail: 0,
    		screenX: window.screenX,
    		screenY: window.screenY,
    		clientX: pos.left + 1,
    		clientY: pos.top + 1,
    		ctrlKey: false,
    		shiftKey: false,
    		altKey: false,
    		metaKey: false,
    		button: 1,
    		buttons: 0,
    		relatedTarget: el
    	});
    	el.dispatchEvent(evtFake);
    
    	window.setTimeout(function() {
    		document.body.removeChild(el);
    	}, 1);
    }
    
    window.setTimeout(function() {
    	clickFire(function() {
    		window.open("http://stackoverflow.com");
    	});
    }, 1000);

    Note: The web browsers are very smart today and we will hardly get cheat them.

    Solution

    Don't use pop-ups ( I hate pop-ups :) ), try simulate "pop-up" using <iframe>: http://demos.jquerymobile.com/1.4.0/popup-iframe/

    Or add um button using modal (like bootstrap) and and place a message asking the user clicks:

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"/>
    
    <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title" id="exampleModalLabel">New message</h4>
          </div>
          <div class="modal-body">
             Open pop-up :)
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
            <button id="popupIsNotPopular" type="button" class="btn btn-primary">Ok</button>
          </div>
        </div>
      </div>
    </div>
    
    window.setTimeout(function() {
        $('#exampleModal').modal();
    }, 2000);
    
    
    $("#popupIsNotPopular").click(function() {
        window.open("http://www.stackoverflow.com");
    });
    
    0 讨论(0)
提交回复
热议问题