Search code examples
javascriptdomxmlhttprequest

Any alternative to synchronous XHR?


I'm interfacing with a third party code (Chrome extension runtime, but it's not relevant to the problem itself). The code blocks until my function returns, which is desired behaviour. To give a meaningful output, my function needs to know the result of XHR. In code terms, it's laid out like this:

function() {
        let xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://example.com', false);
        xhr.send(null);
        if (xhr.status == 200) {
            let jsonResponse = JSON.parse(xhr.responseText);
            return jsonResponse['neededData'];
        } else {
            console.error('API response invalid.');
        };
    };

To me this is one of those use cases that fit the synchronous XHR. Unfortunately, synchronous XHR is being deprecated and wanting to write future-proof code, I'm struggling to find an alternative. I did my research, but none of the options found on internet or SO satisfy my constraints:

  • Fetch - asynchronous
  • Wrapping synchronous XHR in worker thread - asynchronous
  • Rewriting to asynchronous - I have no control over the code I'm interfacing with.

Are there any other options?


Solution

  • I'm interfacing with a third party code (Chrome extension runtime, but it's not relevant to the problem itself)

    Actually, I think the Chrome's runtime is very relevant here. Why? Well, Firefox has solved this! A Firefox extension can return a Promise and still modify request headers. MDN docs for webRequest.onBeforeSendHeaders.

    Yeah, this is confusing behavior on Chrome's part. It's been asked before: BrowserExtension webRequest.onBeforeRequest return promise

    For now, I think you're forced to keep the XHR synchronous. But if you want to be a little fancy, you can try using the async Promise API, and fallback to synchronous when running in Chrome.

    I would view this as Chrome's fault, not your code. Chrome's extension API continues to be strange, like using chrome.runtime.lastError for reporting errors. Firefox, and the Web Extension spec, uses Promises. There are polyfills you can use in Chrome for access to some of the Promise-based APIs, but unfortunately this particular API cannot be polyfilled.