optimize switch code to function args call - javascript

Im using the following code that working OK.
_handleIn: function(Filecontent, config) {
var oExtendedHTML = Filecontent;
switch (config.action) {
case 'new':
oExtended = this._crElement(Filecontent, config);
break;
case 'upd':
oExtended = this._updlement(oExtended, config);
break;
}
return oExtended;
},
Since I new to JS and I want to learn more I read that the switch sometimes can be change to this pseudo coe:
This
function actions(key, args){
switch(key){
case: 'foo':
return doFoo(args);
break;
case: 'bar':
return doBar(args);
break;
case: 'baz':
return doBaz(args);
break
}
}
var value = actions(keyargs);
// To This
var actions = {
foo: function doFoo(){...},
bar: function doBar(){...},
baz: function doBaz(){...}
};
var value = actions[key](args);.
my question is how can I change my code to this? not sure how to pass the key and args, Im using requirejs AMD module.

// your function without `switch`
var _handleInnerElement = {
_createElement: function(){
alert('create');
},
_updateElement: function(){
alert('update');
},
// you can use strings also
'new': function(fileContent, config) {
return this._createElement(fileContent, config);
},
upd: function(fileContent, config) {
return this._updateElement(fileContent, config);
}
}
// some variables to work with
var config = {
action: 'new',
some_data: 123
}
var someFileContent = {};
// usage
_handleInnerElement[config.action](someFileContent, config);

Related

How to refactor multipler if statements into cleaner and easier to read code in javascript?

I have multiple if statements in a function like this :
const handleCat = () => {
if (mainCat === 'car') {
return carCat;
}
if (mainCat === 'mobile') {
return mobileCat;
}
if (mainCat === 'estate') {
return estateCat;
}
if (mainCat === 'other') {
return otherCat;
}
};
All the cat's are arrays with objects . I was wondering how can I refactor this code into much more cleaner and easier to read code ? How many ways are there to refactor multiple if statements in javascript ?
One way which I would recommend will be to use an object type.
const genericCat = {
car : carCat,
mobile : mobileCat,
estate:estateCat,
other : otherCat
}
handleCat = (mainCat)=>{
return(generiCat[mainCat])
}
this approch also saves you from updating your code from more then one place if types of cat are increased.This is like using Enums in Java but with objects.
Using a switch statement:
const handleCat = () => {
switch (mainCat) {
case 'car':
return carCat;
case 'mobile':
return mobileCat;
case 'estate':
return estateCat;
case 'other':
return otherCat;
default:
break;
}
};
A switch statement is an option
const handleCat = (mainCat) => {
switch(mainCat) {
case "car":
return "carCat";
case "mobile":
return "mobileCat";
case "estate":
return "estateCat";
case "other":
return "otherCat";
default:
return "fallbackCat";
}
};
const first = handleCat("car");
const second = handleCat();
console.log(first);
console.log(second);
You could also save the options in an object and return them based on their key.
const handleCat = (mainCat) => {
const fallback = "fallbackCat";
const catMap = {
car: "carCat",
mobile: "mobileCat",
estate: "estateCat",
other: "otherCat",
};
return catMap[mainCat] || fallback;
};
const first = handleCat("car");
const second = handleCat();
console.log(first);
console.log(second);
You can use a switch statement:
var mainCat = 'car';
const handleCat = () => {
switch(mainCat) {
case 'car':
return carCat;
break;
case 'mobile:
return mobileCat;
break;
case 'estate'
return estateCat;
break;
default:
return otherCat;
}
}

can't get data from web worker

I have the following forEach:
hosts.forEach((host) => {
filterByHost(host);
});
as you can see the forEach call the following method where I pretend to use a web worker
function filterByHost(host) {
let sortedHost = [];
const filterHost = data.filter((element) => element.host.includes(host));
if (window.Worker) {
const worker = new Worker('utils.js');
worker.postMessage({ cmd: 'sortHost', filterHost });
worker.onmessage = function (event) {
switch (event.data.cmd) {
case 'sortHost':
servers = {
...servers,
[host]: event.data.data,
};
break;
default:
break;
}
};
}
}
the code inside my utils.js file is the following:
self.addEventListener(
'message',
function (event) {
switch (event.data.cmd) {
case 'uniqueHosts':
postMessage({ cmd: 'other', data: other(event.data.data) });
break;
case 'sortHost':
postMessage({
cmd: 'sortHost',
data: sortHost(event.data.filterHost),
});
break;
default:
break;
}
},
false
);
function other(data) {
return bla bla bla;
}
function sortHost(filterHost) {
return filterHost.sort((a, b) => {
if (a.apdex < b.apdex) {
return 1;
}
if (a.apdex > b.apdex) {
return -1;
}
return 0;
});
}
As you can see I trying to using a web worker in order to sort a big array of objects, and the worker works, it return a sorted array, but when I try to spread the results inside my servers I have and empty array, is like when the forEach call a the new Worker every thing is restarted and I can't find why

Infinite functions calls like 'string'.replace().replace()

I'm not really sure how to explain so I will start with the output.
I need to return this:
{
replies:
[
{ type: 'text', content: 'one' }
{ type: 'text', content: 'two' }
{ type: 'text', content: 'three' }
],
conversation: {
memory
}
}
And I wanted to return that through in-line statement.
So I would like to call something like:
reply.addText('one').addText('two').addText('three').addConversation(memory)
Note that addText can be called infinite times while addConversation can be called only one time. Also conversation is optional, in that case, if conversation is absent the conversation object should not appear in the output.
To create a custom structured object use a constructor, say Reply.
To call instance methods on the return value of method calls, return the instance object from the method.
Choices to prevent multiple additions of conversation objects include throwing an error (as below) or perhaps logging a warning and simply not add additional objects after a first call to addConversation.
Write the code to implement the requirements.
For example using vanilla javascript:
function Reply() {
this.replies = [];
}
Reply.prototype.addText = function( content) {
this.replies.push( {type: "text", content: content});
return this;
}
Reply.prototype.addConversation = function( value) {
if( this.conversation) {
//throw new Error("Only one conversation allowed");
}
this.conversation = {conversation: value};
return this;
};
Reply.prototype.conversation = null;
// demo
var reply = new Reply();
reply.addText( "one").addText("two").addConversation("memory?");
console.log( JSON.stringify( reply, undefined," "));
(The console.log uses JSON stringify to avoid listing inherited methods)
A possible implementation is to create a builder as follows:
function create() {
const replies = []; // store all replies in this array
let conversation; // store the memory here
let hasAddConversationBeenCalled = false; // a state to check if addConversation was ever called
this.addText = function(content) {
// add a new reply to the array
replies.push({
type: 'text',
content
});
return this; // return the builder
};
this.addConversation = function(memory) {
if (!hasAddConversationBeenCalled) { // check if this was called before
// if not set the memory
conversation = {
memory
};
hasAddConversationBeenCalled = true; // set that the memory has been set
}
return this; // return the builder
}
this.build = function() {
const reply = {
replies
};
if (conversation) { // only if converstation was set
reply.conversation = conversation; // add it to the final reply object
}
return reply; // finally return the built respnse
}
return this; // return the new builder
}
You can then use it as follows:
const builder = create();
const reply = builder.addText('one').addText('two').addText('three').addConversation({}).build();
Here is a link to a codepen to play around with.
If you specifically want to add assemble this via multiple function calls, then the builder pattern is your best bet, as vader said in their comment.
However, if the goal is to simply create shorthand for concisely building these objects, it can be done using a function that takes the list of text as an array.
const buildObject = (textArray, memory) => {
return Object.assign(
{},
{
replies: textArray.map(x => {
return {
type: 'text',
value: x
}
})
},
memory ? {conversation: memory} : null
)
}
var memory = { };
//with memory
console.log(buildObject(['one', 'two', 'three'], memory ))
//without memory
console.log(buildObject(['one', 'two', 'three']));
Fiddle example: http://jsfiddle.net/ucxkd4g3/

Return promises in order

I'm facing an issue to return promises using $q#all method.
I want to make promises dependent on each other, i.e.:
If I set obj1, obj2 and obj3 I want to get them in the same order.
How can I achieve this?
Factory:
mainFactory.$inject = ['$http', '$q'];
function mainFactory($http, $q) {
var mainFactory = {
getPromises: getPromises
};
return mainFactory;
function getPromises(id) {
promises = {
'obj1': $http.get('http1'),
'obj2': $http.get('http2'),
'obj3': $http.get('http3'),
'obj4': $http.get('http4', { params: { 'id': id } }),
'obj5': $http.get('http5'),
'obj6': $http.get('http6', { params: { 'id': id } })
};
return $q.all(promises);
}
}
Controller:
MainCtrl.$inject = ['mainFactory'];
function MainCtrl(mainFactory) {
var vm = this;
mainFactory.getPromises(id)
.then(getResponse)
.catch(getError);
function getResponse(response) {
var keys = Object.keys(response), i = keys.length;
while (i--) {
var key = keys[i];
console.log(key); // I want all the keys in order, i.e. => obj1, obj2.. and so on
var value = response[key].data;
switch(key) {
...
}
}
}
function getError(error) {
console.log(error);
}
}
EDIT:
I tried this way also:
var promises = {};
return $http.get('/admin/http1.json').then(function (value) {
promises['obj1'] = value;
})
.then(function (result) {
return $http.get('/admin/http2.json').then(function (value) {
promises['obj2'] = value;
});
}).then(function (result) {
return $http.get('/admin/http3.json').then(function (value) {
promises['obj3'] = value;
});
});
return $q.all(promises);
Using $q.all will resolve each promise in no particular order. If you want them to execute after each promise has been resolve, use promise chaining.
function getPromises(id) {
var getObjA = function () {
return $http.get('http1');
};
var getObjB = function () {
return $http.get('http2');
};
var getObjC = function () {
return $http.get('http3');
};
var getObjD = function () {
return $http.get('http4', { params: { 'id': id } });
};
var getObjE = function () {
return $http.get('http5');
};
var getObjF = function () {
return $http.get('http5', { params: { 'id': id } });
};
return getObjA()
.then(getObjB)
.then(getObjC)
.then(getObjD)
.then(getObjE)
.then(getObjF);
}
Edit: as an additional info, you can catch any error in any of those promise by placing a catch statement here
getPromises("id")
.then(<success callback here>)
.catch(<error callback that will catch error on any of the promises>);
Meaning, once a promise fails, all the succeeding promises below wouldn't be executed and will be caught by your catch statement
Edit 2
Mistake, I just copied you code above without realizing it was an object. LOL.
promises = [
$http.get('http1'),
$http.get('http2'),
$http.get('http3'),
$http.get('http4', { params: { 'id': id } }),
$http.get('http5'),
$http.get('http6', { params: { 'id': id } })
]
Edit 1
Sorry I didn't notice the comments Jared Smith is correct.
Object keys are inherently unordered. Use an array instead.
Edit 0
Object keys wont be ordered. Use array on declaring your promises.
promises = [
$http.get('http1'),
$http.get('http2'),
$http.get('http3'),
$http.get('http4', { params: { 'id': id } }),
$http.get('http5'),
$http.get('http6', { params: { 'id': id } })
]
$q.all(promises)
.then(functions(resolves){
// resolves here is an array
}).catch(function(err){
// throw err
});

Creating json in specific format using javascript

I have a complex javascript code which when simplified is as below..
function getjson1() {
return {
'json1': {
id: 'jsonid1'
}
};
}
function getjson2() {
return {
'json2': {
id: 'jsonid2'
}
};
}
myjson = [];
myjson.push(getjson1());
myjson.push(getjson2());
function finaljson() {
return {
'json': myjson
};
}
console.log(JSON.stringify(finaljson()));
Now the result of this code is
{"json":[{"json1":{"id":"jsonid1"}},{"json2":{"id":"jsonid2"}}]}
Now this code I need to change such that I can get rid of the array and can traverse the json object like.. json.json1.id, etc..
One example could be as below..
{"json":{"json1":{"id":"jsonid1"},"json2":{"id":"jsonid2"}}}
Any help is sincerely appreciated.
Thanks
Well if you don't want an array, don't use one. First, a jQuery-based solution:
myjson = {};
myjson = $.extend(myjson, getjson1());
myjson = $.extend(myjson, getjson2());
In native JavaScript, you can use the following function:
function extend (target, source) {
Object.keys(source).map(function (prop) {
target[prop] = source[prop];
});
return target;
};
This way, the first code becomes this:
myjson = {};
myjson = extend(myjson, getjson1());
myjson = extend(myjson, getjson2());
You are pushing it to an array so you are getting an array.
use this simple add function to push it in an object in the format you want.
First key in the function returns will be the key in the end object.
function getjson1() {
return {
'json1': {
id: 'jsonid1'
}
};
}
function getjson2() {
return {
'json2': {
id: 'jsonid2'
}
};
}
function add(obj, toadd) {
for(var key in toadd) {
if(toadd.hasOwnProperty(key)) {
obj[key] = toadd[key];
break;
}
}
return obj;
}
myjson = {};
add(myjson,getjson1());
add(myjson,getjson2());
function finaljson() {
return {
'json': myjson
};
}
console.log(JSON.stringify(finaljson()));

Categories

Resources