Languages
[Edit]
EN

JavaScript - AJAX / fetch requests with multiplexing

6 points
Created by:
Greg
5140

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);
Native Advertising
50 000 ad impressions - 449$
🚀
Get your tech brand or product in front of software developers.
For more information contact us:
Red dot
Dirask - friendly IT community for everyone.

❤️💻 🙂

Join