Looking for help refactoring the following code to follow a Functional Programming paradigm.
The first function builds a configuration object with default settings and optional presets, while the buildResourcePath
will assemble a URL for the image service.
getSizedUrl
and getSizedSkuUrl
returns a URL that will be used for an image tag.
var imgSvcPath = './imageSizer.svc';
/**
* configureImg
* Build a configurtion object with sane defaults applied that can be used to construct a url for the ImageResizer service
*/
function configureImg( options ){
options = options || {};
var defaults = {
type: null,
src: '',
width: 120,
height: null
},
// use Image presets if an option.type provided
presets = options.type ? Images.getPresets( options.type ) : {};
return $.extend( defaults, options, presets );
};
/**
* buildResourcePath
* Construct a url for the ImageResize service to be used for the src of <img />
*/
function buildResourcePath( svcName, options ){
// imageSizer.svc/GetResizedImage?path=[path]&size=[size]&quality=[quality]
var resourcePath = [],
conf = configureImg( options ),
src = ( conf.skuId !== undefined )
? '?sku=' + conf.skuId
: '?path=' + encodeURI( conf.src ),
size = '&size=' + ( conf.height ? 'h|' + conf.height : 'w|' + conf.width ),
quality = conf.quality ? '&quality=' + conf.quality : '';
resourcePath.push( imgSvcPath, svcName, src, size, quality );
return resourcePath.join( '' );
};
/**
* getSizedUrl
* return src of <img /> for GetResizedImage
*/
var getSizedUrl = function( options ){
if( 'undefined' === typeof options.src ) {
console.error( 'upi.Services.Image::getSizedUrl configuration options must provide an image src string' );
}
return buildResourcePath( 'GetResizedImage', options );
};
/**
* getSizedSkuUrl
* return src for an <img /> for GetResizedSkuImage
*/
var getSizedUrlForSku = function( skuId, options ){
if( 'undefined' === typeof skuId ) {
console.error( 'upi.Services.Image::getSizedSkuUrl configuration options must provide sku ID' );
}
options = options || {};
options[ 'skuId' ] = skuId;
return buildResourcePath( 'GetResizedSkuImage', options );
};
Image = {
getSizedUrlForSku: getSizedUrlForSku,
getSizedUrl: getSizedUrl
};
2 Answers 2
// Store everything in a scope. It's to preven you from polluting the global
// scope as well as protect your code from collisions.
;(function(ns) {
// Pulling out constants into this scope. They only need to be declared once.
var imgSvcPath = './imageSizer.svc';
var defaults = {
type: null,
src: '',
width: 120,
height: null
};
function configureImg(options) {
var options = options || {};
var presets = options.type ? Images.getPresets(options.type) : {};
// It's best if you extend to a blank object. Don't override the defaults.
return $.extend({}, defaults, options, presets);
}
function buildResourcePath(svcName, options) {
var conf = configureImg(options);
// I assume you use jQuery because of $.extend so I introduce $.param
// which takes a map and converts it into a serialized parameter list
var params = {};
// And ternaries can be very messy and unreadable. Now using if-else instead.
if (conf.skuId !== undefined) params.sku = conf.skuId;
else params.path = conf.src;
if (conf.height) params.size = 'h|' + conf.height;
else params.size = 'w|' + conf.width;
if (conf.quality) params.quality = conf.quality;
return imgSvcPath + '?' + $.param(params);
}
// Let's append our API to the namespace
ns.getSizedUrl = function(options) {
if ('undefined' === typeof options.src) {
console.error('upi.Services.Image::getSizedUrl configuration options must provide an image src string')
}
return buildResourcePath('GetResizedImage', options)
};
ns.getSizedUrlForSku = function(skuId, options) {
if ('undefined' === typeof skuId) {
console.error('upi.Services.Image::getSizedSkuUrl configuration options must provide sku ID')
}
options = options || {};
options['skuId'] = skuId;
return buildResourcePath('GetResizedSkuImage', options)
};
// Change your namespace to something else. Image is already taken.
// Image is the constructor for making image elements with JS.
}(this.MyImage = this.MyImage || {}))
Immutability is one of the cornerstones of functional programming.
getSizedUrlForSku
mutates it's argument and hence violates immutability. It's better to make a copy of options
here.
var getSizedUrlForSku = function( skuId, options ){
// ...
optionsCopy = $.extend( {skuId: skuId}, options )
return buildResourcePath( 'GetResizedSkuImage', optionsCopy );
};
Explore related questions
See similar questions with these tags.