3
\$\begingroup\$

I've wrote a pretty useful method to prevent multiple requests per single get url. There is a well known pattern - to store promise and return it for each next request. But there is too much copy/paste for my taste. So, please check my solution. Maybe you can give me advice to make it better or maybe point at any mistakes.

Here it is (working plunker):

promisedService.$inject = ['$q', '$http', '$httpParamSerializer'];
function promisedService($q, $http, $httpParamSerializer){
    
    var promisesInProgress = {};
    
    return {
        
        singleGet: singleGet
        
    }
   
    /** 
     * you can pass:
     * url
     * url and callback function
     * url, params and callback function
     */
    function singleGet(url){

        var params, preResolve;
        if(arguments.length == 3){
            preResolve = arguments[2];
            params = arguments[1];
        }
        else if(arguments.length == 2){
            if(typeof arguments[1] === 'function'){
                preResolve = arguments[1];
            }
            else {
                params = arguments[1]
            }
        }

        // creating unique key based on URL + params
        var requestUrl = _buildUrl(url, params);

        // checking for promise. If promise already exists - returning it
        if(promisesInProgress.hasOwnProperty(requestUrl)) {
            return promisesInProgress[requestUrl];
        }

        // else - saving new promise
        var deferred = $q.defer();
        promisesInProgress[requestUrl] = deferred.promise;
        
        // sending a request
        $http.get(url, params).then(function(response){
            console.log('server request');
            
            // if callback was passed, wrapping it in promise and returning
            // why do we need a callback. In case we need to cache data
            if(preResolve){
                $q.when(preResolve(response)).then(function(data){
                    deferred.resolve(data);
                });
            }
            else
            //else - returning data as is
                deferred.resolve(response);
            delete promisesInProgress[requestUrl];
        }, function(error){
            deferred.reject(error);
            delete promisesInProgress[requestUrl];
        });

        return deferred.promise;
    }

    /////////////////////////////// PRIVATE /////////////////////////////////

    function _buildUrl(url, params) {
        var serializedParams = $httpParamSerializer(params);

        if (serializedParams.length > 0) {
            url += ((url.indexOf('?') === -1) ? '?' : '&') + serializedParams;
        }

        return url;
    }
}

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.