JavaScript delay navigation until callback/timeout

TLDR: you can't, see bottom of question for alternative solution (ie the one I compromised with).

I have an async function that sends data to a server on a link click, of course this will most likely not get sent because of the page unload timing.

Is there any way that I can either delay the effect of the click until either the callback function runs or a timeout occurs (both would be in effect, the timeout there to cap the possible delay).

click => wait for timeout/callback => continue with normal event.

OR

click => start call & timeout, cancel default functionality callback/timeout calls function to continue/restart click process

I hope that all makes sense, thanks in advance.

EDIT: the server call does not need to complete 100% of the time.

EDIT: I want to continue the original "function" of the click event and not replace or edit the window.location variable as navigation is not guaranteed with onclick for example, middle-click.

EDIT: here is the basic structure of the code (it's really complicated en-situe):

item.onclick = function(){

var callback = function(){
    // continue as if nothing happened
    // including non-navigational clicks (e.g. middle-click)
};

// Send call with callback
sendCall(callback);

// if no callback not triggered in 250ms then continue anyway
setTimeout(callback, 250);

return false; // or not if there's a way to delay
}

EDIT: There seems to be no useful solution for what I want to do here so I've posted the code I used in an answer.


You can prevent the default action of the click so the link is not actually fired on the click. Then you send your ajax call and when it completes, then your code changes to the new page itself.

Assuming you already have a click handler for the link that you are doing the ajax call in:

function myClickHandler(e) {
    e.preventDefault();
    var self = this;
    sendAjax(..., function() {
        // ajax call done here
        // do the page navigation
        window.location = self.href;
    })
}

You will probably want to create some user feedback that the click is being processed since the user may see nothing happen until after a short delay (while your ajax call is being processed) and you don't want to encourage the user to click again because it appears nothing happened. You may even want to prevent multiple clicks while the ajax call is being processed.


Response to your edit:

There is no method in Javascript to block Javascript execution for a maximum of 250ms while processing an async ajax call and then continue normal execution. So, the outline in your code is not directly possible as you've shown it.

The usual design pattern in Javascript is to prevent the default action, set up your async action (ajax call and timer in your case) and then when that async event completes or times out, you then manually trigger what the default action would have been. But you have to know how to trigger the default action yourself in order to do that (which is what my code suggestion above showed).

The only work-around I can think of is that you could send a synchronous Ajax call (generally considered a bad practice) with a timeout set on the ajax call itself. This would suspend execution of your Javascript and all other interaction with the page until the ajax call either completes or times out. You'd have to test this pretty thoroughly to see if it gives you the desired interaction in lots of browsers because it's certainly not a standard thing that is used regularly. I personally would not recommend it (synchronous ajax is just evil as it locks up the browser).

With a fuller understand of what problem you're really trying to solve, I would look for a better designed solution. So far, you've only described your attempted solution, not the actual problem you're trying to solve. This is known as the XY problem and drastically limits how we can help you.


If you want to do something after a successful ajax then as the user before me mentioned you can use the ajax success function to trigger the desired behavior along with 'mousedown'/'touchstart' to save some ms instead of 'click' .

jQuery('body').on('click','yourlink',function(e){
    e.preventDefaul;
    $.ajax({
        url: 'url here',
        type: 'POST',
        success: function() {
        //go to desired url
            window.location.replace = 'the url to navigate to';
        },
        error : function(){
         //ajax error handling code here
        }
     });
});

Didn't really understand what you mean by " I cannot use the window.location trick" but hope this helps.

Cheers


这是我最终使用的代码,它检查点击是左键点击还是点击:

element.onclick = function(event){
    if(event.button == 0){
        var callback = function(){
            window.location = destinationUrl;
        };
        sendCall(callback);
        setTimeout(callback, 250);
        return false; // halt normal click propagation
    } else {
        sendCall();
    }
};
链接地址: http://www.djcxy.com/p/83718.html

上一篇: 如何在d3.js中的不同元素上进行链式转换?

下一篇: JavaScript延迟导航,直到回调/超时