简体   繁体   中英

Best practice for getting around limitation on concurrent ajax calls

At the risk of getting roasted for not posting code, what is the best way for getting around the 6 concurrent call limitation for ajax requests?

So currently I'm working with an application that can have up to 40 or so ajax requests on page load. For background, most of these requests are for various graphs, hidden behind tabs. There are some requests that can be triggered by the user (such as updating the name of an entity without refreshing the page). This means that with the limitation on concurrent requests the user won't be able to change anything until there's only 5 other requests running, and that's an unacceptable user experience.

This may mean that the app is structured badly, but most of the things loading are not required right away.

Anyway, I've looked a bit into fetch() and webworkers but can't find any information on whether these would help get around the limitation.

One solution would be to put resources on different subdomains, but this makes the backend API unnecessarily complicated (and it's a browser issue, not a server issue).

I've considered these approaches:

  • delay requests until the user actively needs them (IMO this is a bad user experience because they will have to wait a little bit a lot, which is annoying)
  • create a queuing system that leaves open one spot for user initiated requests (I'm not sure how to implement this, but it should be doable)
  • restructure the API so that more data is returned per request (this again is mainly a backend solution that feels a little dirty and unRESTful. Also it won't necessarily improve the load time)
  • chaining calls such as with Multiple Async AJAX Calls Best Practice (however given there are an unpredictable number of calls on unrelated endpoints so I don't think this is all that practical here)
  • webworkers? (again, not sure if this could help, since this is used to multithread js)
  • fetch()? (I can't find info on whether this is subject to the same limitation)

This is very much opinion based.

40 requests is not unreasonable but depending on your server and site setup it can take quite a while.

With that many calls I would bundle some of them together in a initializePage=X call. This does involve some serverside work.

Delay requests is not necessarily bad, depending on your estimated time to deliver. If possible you could present some kind of animation or "expected result" until the response ticks in, to keep the user entertained. The same applies to Queing your requests.

Restructuring your code to return everything in a bundle could also greatly speed up your site if you run a lot of initialization on your server (like security checks).

If performance is still a concern you can look into connections that provide faster results such as EventSource or WebSocket . Such a faster connection also allows for a more flexible approach to chaining. EventSource, for instance, supports events, so you could set several events on a single, bundled request and fire them as the server returns data.

Webworkers is not the answer, as the problem here is connection speed and concurrent connection limits.

I don't think we can answer this question directly. Several of the solutions you have mentioned are viable but vary by level of effort. If you are willing to adjust architecture you can consider a GraphQL approach which can wrap the bundling for you. I would also say that you can maintain REST but have a special proxy service that bundles data for you. I'd also say, don't let RESTfullness dictate or force how you develop.

Also, delaying requests until the user needs them seems like the appropriate choice to me. It's the basis for why we have "above the fold" CSS styling and infinite scrolling. Load what is needed right now first and defer the stuff that might not actually matter when it needs to be.

Concurrency of AJAX calls would come into picture if these requests are called from one thread. If WebWorker is used with AJAX then no issues at all, reason being each instance of webworker will be isolated, in a thread that is not in the main thread.

I would call that as JaxWeb and I will be pushing a git repo in coming week where you may find pure JS code that takes care of it. This is being tested right now, but yeah it does solve the problem.

Example:

Add below code in JaxWeb.js

onmessage = function (e) {
    var JaxWeb = function (e) {
        return {
            requestChannel: {},
            get_csrf_token: function () {
                return this._csrf_token;
            },
            set_csrf_token: function (_csrf_token = null) {
                this._csrf_token = _csrf_token;
            },
            prepare: (function ( e ) {
                this.requestChannel = new XMLHttpRequest();
                this.requestChannel.onreadystatechange = function () {
                    if (this.readyState == 4 && this.status == 200) {
                        postMessage(JSON.parse(this.responseText));
                    }
                };
                this.requestChannel.open(e.data.method, e.data.callname, true);
                this.requestChannel.setRequestHeader("X-CSRF-TOKEN", e.data.token);
                var postData = '';
                if (e.data.data)
                    postData = JSON.stringify(e.data.data);
                this.requestChannel.send(postData);
            })(e)
        }
    };
    return JaxWeb(e);
}

Usage:

jaxWebGetServerResponse = function () {
    var wk2 = new Worker('path_to_jaxweb_js/JaxWeb.js');

    wk2.postMessage({
        "callname": '<url end point>',
        "method": '<your http method>',
        "data": ''
    });

    wk2.onmessage = function (serverResponse) {
        //
        //process results
        //with data that is received from server
    }
};



//Invoke the function 
jaxWebGetServerResponse();

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