Languages
[Edit]
EN

JavaScript - AJAX / fetch requests with multiplexing

6 points
Created by:
Greg
1505

In this short article we would like to show how to write in JavaScript own logic that joins in proper order as single array of results of many requests. Presented solution uses as configuration to know about items distibution in returned list. When it is necessary the logic maked AJAX request to complete needed data.

Example code:

// ONLINE-RUNNER:browser;

function RequestMultiplexer(proportions, request) {
    var capacity = 0;
    var states = [ ];
    var processing = false;
    var instances = { };
    for (var i = 0; i < proportions.length; ++i) {
        var proportion = proportions[i];
        var type = proportion.type;
        var count = proportion.count;
        var instance = instances[type];
        if (instance) {
            instance.limit += count;
        } else {
            instances[type] = {
                offset: 0,
                limit: count,
                storage: [ ]
            };
        }
        capacity += count;
    }
    for (var i = 0; i < proportions.length; ++i) {
        var proportion = proportions[i];
        states.push({
            type: proportion.type,
            limit: proportion.count,
            instance: instances[proportion.type]
        });
    }
    function removeState(type) {
        for (var i = states.length - 1; i > -1; --i) {
            var state = states[i];
            if (state.type == type) {
                states.splice(i, 1);
            }
        }
    }
    this.request = function(callback) {
        if (processing || states.length == 0) {
            return false;
        }
        processing = true;
        var index = 0;
        var state = states[index];
        var share = state.limit;
        var instance = state.instance;
        var storage = instance.storage;
        var result = [ ];
        var change = function() {
            index += 1;
            if (index >= states.length) {
                index = 0;
            }
            state = states[index];
            share = state.limit;
            instance = state.instance;
            storage = instance.storage;
        };
        var repeat = function() {
            setTimeout(iterate);
        };
        var navigate = function() {
            change();
            repeat();
        };
        var complete = function() {
            var count = Math.min(state.limit, storage.length, capacity - result.length);
            if (count > 0) { // page is not completed yet
                var slice = storage.splice(0, count);
                for (var i = 0; i < slice.length; ++i) {
                    result.push(slice[i]);
                }
                if (result.length < capacity) {
                    share -= slice.length;
                    if (share > 0) {
                        return repeat();
                    }
                    return navigate();
                }
            }
            processing = false;
            return callback(result);
        };
        var iterate = function(){
            var count = Math.min(state.limit, capacity - result.length);
            if (count > storage.length) { // data should be fetch by additional request
                var commit = function(data, disable) {
                    if (disable) {
                        remove(state.type);
                    }
                    if (data.length > 0) {
                        instance.offset += data.length;
                        for (var i = 0; i < data.length; ++i) {
                            storage.push({
                                type: state.type,
                                data: data[i]
                            });
                        }
                        complete();
                    } else {
                        navigate();
                    }
                };
                request(state.type, instance.offset, commit);
            } else {
                complete();
            }
        };
        setTimeout(iterate);
        return true;
    };
}

// Example usage:

// We want to mix data following way:
//   message picture picture picture video video
//   message picture picture picture video video
//   message picture picture picture video video
//   etc.

var proportions = [
    { type: 'message', count: 1 },
    { type: 'picture', count: 3 },
    { type: 'video',   count: 2 }
];

var request = function(type, offset, callback) {
    console.log('REQUEST FOR: ' + type + 's');
    //TODO: request with AJAX to proper link type and callback call
    var response = [
        { id: offset + 0, name: 'Item name' },
        { id: offset + 1, name: 'Item name' },
        { id: offset + 2, name: 'Item name' },
        { id: offset + 3, name: 'Item name' },
        { id: offset + 4, name: 'Item name' },
        { id: offset + 5, name: 'Item name' }
    ];
    callback(response);
};

var requester = new RequestMultiplexer(proportions, request );

function execute(counter) {
  	if (counter == 0) {
    	return;
    }
    var callback = function(response) {
        // response contains combined data according to proportions
        for (var i = 0; i < response.length; ++i) {
            var item = response[i];
            console.log('JOINED: ' + item.type + '-' + item.data.id + ' ' + item.data.name);
        }
      	execute(counter - 1);
    };
  	requester.request(callback);
}

execute(3);
Hey 👋
Would you like to know what we do?
  • Dirask is a friendly IT community for learners, professionals and hobbyists to share their knowledge and help each other in extraordinary easy way.
  • We welcome everyone,
    no matter what the experience,
    no matter how basic the question is,
    this community will help you.