简体   繁体   中英

How can I achieve javascript sync xmlhttprequest with timeout when it is not supported?

I have searched high and low for alternatives (Promise, async calls, etc) but couldn't yet find a solution that would work.

I have a fairly typical situation like:

blockingCallBackFunctionFor3rdPartyLibraryAPI(url)
{
    responseCode = cloudLookupCall(url); // async or sync call over the web
    if (responseCode == "Deny")
    {
        // Return "Deny" URL decision to external library/API
    }

    // Return default "Allow" decision
}

function cloudLookupCall(url)
{
    var hdl = new XMLHttpRequest();
    hdl.open(method, url, true/false); // true/false based on async/sync

    // use standard XHR stuff to get responseText
    return responseText;
}

Now:

  1. If I used ASYNC calls with promise, callbacks whatever, I still need to return some decision to the 3rd party library rightaway because a) JS doesn't support sleeping/waiting, b) I can't use a callback from the async onload() because by that time the 3rd party API already moved on to other URLs
  2. If I instead use SYNC calls I run the risk of blocking indefinitely. I am already using timeouts on the web cloud handler so it doesn't take too long and also handling onerror(), but still worry that the sync call could just stay stuck for too long.

I just don't get why the JS implementation decided to not support timeouts for sync calls when that's exactly where you seem to need it the most (to avoid hanging the browser perpetually).

I have read a ton of forum responses that suggest Promise and async callbacks - but please note above why those will not work - I need an action rightaway OR I need a way to make JS wait. I can't not-wait and not-reply with an action as well.

I am fairly convinced at this point that I am stuck with SYNC calls but what to see what the state of the art is in ensuring it does not block perpetually (and ASYNC is not an alternative). Would making sure that my web php handler timeout in 1 second using set_time_limit() solve the issue of indefinitely hanging?

If possible try to add a function as parameter to the cloudLookupCall() :

function cloudLookupCall(func){
    // your stuff here

    // and when it's needed for you to callback
    if (typeof func === 'function'){
        func();
    }
}

Then in your script:

responseCode = cloudLookupCall(function(data){
    // continue here
});

If that doesn't work this is a wrapper I use as backup when callbacks or promises are not available and I need to fallback using the timeout functionality:

// @param (callback): function to be run when done
// @param (delay): integer in milliseconds
// @param (id): string value of a unique event id
delayedEvent: (function () {
    var timers = {},
        defEvent = cfg.events;

    return function (callback, delay, id) {
        delay = delay || 1000;
        id = id || 'some id';

        if (timers[id]) {
            clearTimeout(timers[id]);
        }

        timers[id] = setTimeout(callback, delay);
    };
})(),

You can use it like this:

responseCode = cloudLookupCall();

delayedEvent(function(){
    if (responseCode === "Deny"){
        // continue here
    }
}, 1000, 'cloudlookup');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM