admin管理员组文章数量:1208155
I'm trying to refactor the following node.js code.
Each case generates a thumbnail, chaining a different set of GraphicMagic transformation to an image.
switch(style.name) {
case 'original':
gm(response.Body)
.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option)
.toBuffer(function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } });
break;
case 'large':
gm(response.Body)
.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option)
.quality(style.quality)
.strip().interlace('Plane')
.toBuffer(function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } });
break;
case 'medium':
gm(response.Body)
.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option)
.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset)
.repage('+')
.strip().interlace('Plane')
.toBuffer(function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } });
break;
case 'small':
gm(response.Body)
.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option)
.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset).repage('+')
.quality(style.quality)
.strip().interlace('Plane')
.toBuffer(function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } });
break;
}
However, all cases share a number of transformations at the beginning and the end of the chaining, so there's room for refactoring. I tried refactoring with the following approach, but the code seems incorrect:
gm(response.Body)
.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option, function(err, response) {
if (style.name === 'original'){
return response;
} else if (style.name === 'large'){
return response.quality(style.quality)
} else if (style.name === 'medium'){
return response.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset).repage('+')
} else if (style.name === 'small'){
return response.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset).repage('+').quality(style.quality)
}
}).(function(response) {
return (stryle.name !== 'original') ? response.strip().interlace('Plane') : return response;
}).(function(argument) {
return response.toBuffer(function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } });
});
I'm trying to refactor the following node.js code.
Each case generates a thumbnail, chaining a different set of GraphicMagic transformation to an image.
switch(style.name) {
case 'original':
gm(response.Body)
.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option)
.toBuffer(function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } });
break;
case 'large':
gm(response.Body)
.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option)
.quality(style.quality)
.strip().interlace('Plane')
.toBuffer(function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } });
break;
case 'medium':
gm(response.Body)
.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option)
.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset)
.repage('+')
.strip().interlace('Plane')
.toBuffer(function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } });
break;
case 'small':
gm(response.Body)
.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option)
.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset).repage('+')
.quality(style.quality)
.strip().interlace('Plane')
.toBuffer(function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } });
break;
}
However, all cases share a number of transformations at the beginning and the end of the chaining, so there's room for refactoring. I tried refactoring with the following approach, but the code seems incorrect:
gm(response.Body)
.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option, function(err, response) {
if (style.name === 'original'){
return response;
} else if (style.name === 'large'){
return response.quality(style.quality)
} else if (style.name === 'medium'){
return response.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset).repage('+')
} else if (style.name === 'small'){
return response.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset).repage('+').quality(style.quality)
}
}).(function(response) {
return (stryle.name !== 'original') ? response.strip().interlace('Plane') : return response;
}).(function(argument) {
return response.toBuffer(function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } });
});
Share
Improve this question
asked Nov 24, 2015 at 0:07
SbbsSbbs
1,6703 gold badges22 silver badges35 bronze badges
3
|
2 Answers
Reset to default 12I wouldn't go for a switch
at all.
There is no reason to use chaining at all here. Just do
// if (!/^(original|large|medium|small)$/.test(style.name)) throw new Error(…);
var x = gm(response.Body)
.setFormat('jpg')
.autoOrient()
.resize(style.w, style.h, style.option);
if (style.name == "medium" || style.name == "small")
x = x.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset)
.repage('+');
if (style.name == "large" || style.name == "small")
x = x.quality(style.quality);
if (style.name == "large" || style.name == "medium" || style.name == "small")
// possibly better than if (style.name != "original")
x = x.strip()
.interlace('Plane');
x.toBuffer(next);
But if you're having a large set of options so that it gets unreadable, better factor out each transformation in a function:
function resizedJpg(x) {
return x.setFormat('jpg').autoOrient().resize(style.w, style.h, style.option);
}
function cropped(x) {
return x.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset).repage('+');
}
function withQuality(x) {
return x.quality(style.quality);
}
function stripped(x) {
return x.strip().interlace('Plane');
}
And then apply them separately:
({
original: [resizedJpg],
large: [resizedJpg, withQuality, stripped],
medium: [resizedJpg, cropped, stripped],
small: [resizedJpg, cropped, withQuality, stripped]
}[style.name]).reduce(function(x, trans) {
return trans(x);
}, gm(response.Body)).toBuffer(next);
I wrote small js helper for such usecases: https://github.com/sms-system/conditional-chain
With the help of this tool, you can chain methods optional, based on condition. Code will be more controlled and readable.
cond(gm(response.Body)
.setFormat('jpg')
.autoOrient()
.resize(style.w, style.h, style.option))
.if(style.name == 'medium' || style.name == 'small', gm => gm
.crop(style.w, style.h, style.crop.x_offset, style.crop.y_offset)
.repage('+'))
.if(style.name == 'large' || style.name == 'small', gm => gm
.quality(style.quality))
.if(style.name != 'original', gm => gm
.strip()
.interlace('Plane'))
.end().toBuffer(next)
本文标签: nodejsConditionally chain functions in JavaScriptStack Overflow
版权声明:本文标题:node.js - Conditionally chain functions in JavaScript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738742604a2109938.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
).(
<<< this seems odd – Roko C. Buljan Commented Nov 24, 2015 at 0:09{"original":resp1, "normal":resp2, etc...}
– Roko C. Buljan Commented Nov 24, 2015 at 0:11resize
taking afunction(err, response)
callback in the first snippet? – Bergi Commented Nov 24, 2015 at 0:15