Javascript: Caching within Closure doesn't work - javascript

I am trying to cache the result of the variable "url" in APP.findUrlParameter(). When executing the function the 2nd time, url should not be undefined anymore, but unfortunately it is.
example url: mypage.com?test=123&name=tom
(function () {
var APP = {
urlParameterPairs: function () {
var url;
if (window.location.search) {
url = window.location.search;
url = url.substring(1).split('&');
$.each(url, function (i) {
url[i] = url[i].split('=');
});
}
return url;
},
findUrlParameter: function (key) {
var url; // <---- to be cached !
console.log(url);
return (function () {
var result;
url = url || APP.urlParameterPairs();
$.each(url, function (i) {
var pair = url[i];
if (pair[0] === key) {
result = pair[1];
return false;
}
});
return result;
}());
}
};
console.log('name: ' + APP.findUrlParameter('name'));
console.log('test: ' + APP.findUrlParameter('test'));
}());
logs:
undefined
name: tom
undefined
test: 123
expected:
undefined
name: tom
Array: ["name", "tom"],["test", "123"]
test: 123

Thanks for the answers, of course "url" gets redeclared, stupid me didn't notice. I could solve it with wrapping a closure around it and returning a function like this:
findUrlParameter: (function () {
var url;
function f(key) {
var result;
url = url || APP.urlParameterPairs();
$.each(url, function (i) {
var pair = url[i];
if (pair[0] === key) {
result = pair[1];
return false;
}
});
return result;
}
return f;
}())

Related

Get return value of worker.onmessage inside a function?

I have created a Caching (Memoized) function which takes another function as a parameter
The following is the function which is being cached. The function utilises a worker. The issue here is that if
var hello = GetSubRegion(1233) ,then hello is undefined because the function inside onmessage returns a value but not the parent GetSubRegion function.
function GetSubRegion(selectedMainRegion){
if (typeof(subRegWorker) != "undefined") {
subRegWorker.terminate();
}
subRegWorker = new Worker("subRegWorker.js");
subRegWorker.onmessage = function(e) {
var workData = e.data;
jQuery("#_sub_region").html(workData);
subRegWorker.terminate();
return workData;
}
var result = subRegWorker.postMessage(selectedMainRegion);
return result;
}
The following is the caching function. Due to the above issue, there is no value returned for let result = fun(n) , and hence nothing is cached.
function memoizer(fun){
let cache = {}
return function (n){
if (cache[n] != undefined ) {
return cache[n]
} else {
console.log(n);
let result = fun(n)
cache[n] = result
return result
}
}
}
How to solve this ?
The following is how I am calling the cached function.
jQuery("#_main_region").change(function() {
var getCacheSub = memoizer(GetSubRegion);
var inputMainRegion = jQuery('#_main_region').find(":selected").val();
getCacheSub(inputMainRegion);
});
The caching issue was solved as follows, the changed code is market as comment -
var cache = {};
function memoizer(fun){
return function (n){
if (cache[n] != undefined ) {
jQuery("#_sub_region").html(cache[n]); // This was changed
return cache[n]
} else {
console.log(n);
cache[n] = result
return result
}
}
}
function GetSubRegion(selectedMainRegion){
if (typeof(subRegWorker) != "undefined") {
subRegWorker.terminate();
}
subRegWorker = new Worker("subRegWorker.js");
subRegWorker.onmessage = function(e) {
var workData = e.data;
cache[n] = workData // This was changed
jQuery("#_sub_region").html(workData);
subRegWorker.terminate();
return workData;
}
subRegWorker.postMessage(selectedMainRegion);
}

How to access String in Closure

by triggering xyEvent I want to concatenate a string. But myClosure() is always empty. Why? Thanks for help.
first.js:
$(document).ready(function () {
$("#...").on("tap", function () {
myClosure(new Item());
});
...
}
second.js
var string;
xyEvent {
string = "hello" + myClosure(); // here is the problem
});
var myClosure = (function () {
var anyString = "";
return function (item) {
if(item != null){
anyString = anyString.concat(item.name);
consloge.log(anyString); // perfect at this point
}
else{
return anyString;
}
}})();
I don't know. But this code here works fine.
It prints
a
ab
abc
result = abc
 
var myClosure = (function () {
var anyString = "";
return function (item) {
if(item != null){
anyString = anyString.concat(item.name);
console.log(anyString); // perfect at this point
}
else{
return anyString;
}
}})();
myClosure({name: "a"});
myClosure({name: "b"});
myClosure({name: "c"});
console.log("result = " + myClosure());

Javascript - Looping through an array of valid URL's

I need some help with this for loop.. my code is supposed to run on these specific url's but It seems to skip over the loop and apply to all pages. Thanks
$(document).ready(function () {
if (isValidUrl()) {
displayBoot();
setupBootEvents();
}
});
function isValidUrl() {
var isValid = false,
validUrls = [
"/sport/btts-match-result",
"/sport/double-delight",
"/sport/recently-paid-out",
"/promotions",
"/promotions/Sports",
"/lotto",
"/virtual",
"/bingo"
];
for (var i in validUrls) {
var currentUrl = window.location.pathname + window.location.search;
if (currentUrl == validUrls[i]) {
isValid = true;
}
}
//return isValid;
return true;
}
function displayBoot() {...
function setupBootEvents() {...
Modify your function a bit
function isValidUrl() {
validUrls = [
"/sport/btts-match-result",
"/sport/double-delight",
"/sport/recently-paid-out",
"/promotions",
"/promotions/Sports",
"/lotto",
"/virtual",
"/bingo"
];
for (var i in validUrls) {
var currentUrl = window.location.pathname + window.location.search;
if (currentUrl == validUrls[i]) {
return true;
}
}
return false;
}

apply parameter into function within parameter array

http://jsbin.com/ukizof/1/
how do you call a function which is part of a array and set a paramater to it , as in the example below i want the script to return a function in order to call a function parameter which as below in the example is set below.
var bQuery = {
one: function(elem, options) {
options = this.extend({
method: 'html',
event: 'test2',
func:null
}, options || {});
var element = elem;
if (options.method == 'html') {
element.innerHTML = options.event;
} else if (options.method == 'append') {
element.innerHTML = element.innerHTML + options.event;
} else if (options.method == 'prepend') {
element.innerHTML = options.event + element.innerHTML;
}
return // return method to apply string to func: parameter function as below is "e"
},
extend: function(a, b) {
for (var prop in b) {
a[prop] = b[prop];
}
return a;
}
};
$ = bQuery;
$.one(document.getElementById("log"), {
method: 'append',
event: 'rjfjfjjffj',
func: function(e){
alert(e);
}
});
If I understood you right, you want
var options, element;
…
return function() {
if (typeof options.func == 'function')
return options.func(element.innerHTML);
};

Running multiple javascript object methods together

I am trying to write a little helper class for my ajax chat system i am working on just trying to add basic functions that i may need.
var strings = {
filterWords: ["fool", "dumb", "arse"],
removeSpecialChars: function (str) {
return str.replace(/[^\w\s]/gi, '');
},
killSpace: function (str) {
return str.replace(/\s/g, '');
},
reduceSpace: function (str) {
return str.replace(/\s+/g, ' ');
},
allowLetsAndNums: function (str) {
return str.replace(/[^A-Za-z0-9]/g, ' ');
},
allowLets: function (str) {
return str.replace(/[^A-Za-z]/g, ' ');
},
allowNums: function (str) {
return str.replace(/[^0-9]/g, ' ');
},
wordFilter: function (str) {
var rgx = new RegExp(this.filterWords.join("|"), "gi");
return str.replace(rgx, "****");
}
}
What i am finding is i may need to run multiple methods together i am asking whats the best practise to do this without resulting with below?
alert(strings.wordFilter(strings.reduceSpace(strings.allowLets("efgwge #£235%^#£ fool you a dumb arse432345$%^"))));
Thanks
You could make this a fluent interface, allowing code like this:
var x = new Validation("efgwge #£235%^#£ fool you a dumb arse432345$%^");
alert(x.allowLets().reduceSpace().wordFilter().result());
// alerts "efgwge **** you a **** ****"
Your main code would need to be:
var Validation = function(str) {
this.str = str;
filterWords = ["fool", "dumb", "arse"]
this.removeSpecialChars = function () {
this.str = this.str.replace(/[^\w\s]/gi, '');
return this;
};
this.killSpace = function () {
this.str = this.str.replace(/\s/g, '');
return this;
};
this.reduceSpace = function () {
this.str = this.str.replace(/\s+/g, ' ');
return this;
};
this.allowLetsAndNums = function () {
this.str = this.str.replace(/[^A-Za-z0-9]/g, ' ');
return this;
};
this.allowLets = function () {
this.str = this.str.replace(/[^A-Za-z]/g, ' ');
return this;
};
this.allowNums = function () {
this.str = this.str.replace(/[^0-9]/g, ' ');
return this;
};
this.wordFilter = function () {
var rgx = new RegExp(filterWords.join("|"), "gi");
this.str = this.str.replace(rgx, "****");
return this;
};
this.result = function(){
return this.str;
};
}
Live example: http://jsfiddle.net/fb7en/
You could extend the String prototype:
String.prototype.removeSpecialChars = function () {
return this.replace(/[^\w\s]/gi, '');
}
String.prototype.killSpace = function () {
return this.replace(/\s/g, '');
}
var foo = "This is my§$% String";
​document.write​(foo.removeSpecialChars​().killSpace());​
You could add the functions to the String.prototype so you can call the functions like this:
String.prototype.killSpace = function() {
return this.replace(/\s/g, '');
}
String.prototype.reduceSpace = function () {
return this.replace(/\s+/g, ' ');
}
"foo bar".reduceSpace().killSpace(); // => returns foobar
Only downside to this is that you can't iterate over a string with a for..in loop then because it will list the method as a member and there's currently no cross-browser way to make it non-iterable (IE doesn't support it).
You might consider a chainable API for your Object:
var StringFilter = {
_string: '',
string: function (string) {
this._string = string || '';
return this;
},
filterWords: ["fool", "dumb", "arse"],
removeSpecialChars: function () {
this._string = this._string.replace(/[^\w\s]/gi, '');
return this;
},
killSpace: function () {
this._string = this._string.replace(/\s/g, '');
return this;
},
reduceSpace: function () {
this._string = this._string.replace(/\s+/g, ' ');
return this;
},
allowLetsAndNums: function () {
this._string = this._string.replace(/[^A-Za-z0-9]/g, ' ');
return this;
},
allowLets: function () {
this._string = this._string.replace(/[^A-Za-z]/g, ' ');
return this;
},
allowNums: function () {
this._string = this._string.replace(/[^0-9]/g, ' ');
return this;
},
wordFilter: function () {
var rgx = new RegExp(this.filterWords.join("|"), "gi");
this._string = this._string.replace(rgx, "****");
return this;
},
select: function () {
return this._string;
}
};
StringFilter
.string("efgwge #£235%^#£ fool you a dumb arse432345$%^")
.allowLets()
.reduceSpace()
.wordFilter()
.select();

Categories

Resources