Can you please help answering this. Please not the contraints.
var myLib = {
var callback_one = function (result_from_web_service) {
console.log('callback_one');
};
var callback_one = function (result_from_web_service) {
console.log('callback_two');
};
var init = function () {
console.log('initializing...');
async_call_one(callback_one);
async_call_two(callback_two);
};
var doStuff = function () {
console.log('doStuff is called');
};
};
// User of my library
myLib.init();
myLib.doStuff();
// output
initializing...
doStuff is called
callback_one
callback_two
// What i need:
initializing...
callback_one
callback_two
doStuff is called
Constraint:
calling myLib.init shall not end up calling myLib.doStuff. i.e. myLib.init should be independent of myLib.doStuff
myLib.doStuff() should be called after myLib.init() and its callbacks are returned.
Thanks,
//You must change your API so init is async
//There is no way to have it wait until all initialization is done before it retuns
var init = function (initDone) {
console.log('initializing...');
var n = 0;
function serviceDone(){
n++;
if(n >= 2){ initDone() }
}
async_call_one(function(x){ callback_one(x); serviceDone() });
async_call_two(function(x){ callback_two(x); serviceDone() });
};
// User of my library
myLib.init(function(){
myLib.doStuff();
})
The way I parallelized those calls is very ad-hoc s not the most maintainable (there I need to keep the calls to serviceDone and the value of N in sync).. In the long run I would recommend using one of the many JS async programming libs out there.
hugomg has a good answer.
Yet I think it is really specific and could benefit a sort of workflow implementation, like this (approximately...):
function void() {}
var myLib = {
var g_flow = [];
g_flow[this.init] = [];
g_flow[this.init]["whendone"] = this.callback_one;
g_flow[this.init]["done"] = false;
g_flow[this.callback_one] = [];
g_flow[this.callback_one]["whendone"] = this.callback_two;
g_flow[this.callback_one]["done"] = false;
g_flow[this.callback_two] = [];
g_flow[this.callback_two]["whendone"] = this.doStuff;
g_flow[this.callback_two]["done"] = false;
g_flow[this.doStuff] = [];
g_flow[this.doStuff]["whendone"] = void;
g_flow[this.doStuff]["done"] = false;
var callback_one = function (result_from_web_service) {
console.log('callback_one');
};
var callback_one = function (result_from_web_service) {
console.log('callback_two');
};
var init = function () {
console.log('initializing...');
};
var doStuff = function () {
console.log('doStuff is called');
};
var flow_onward(hwnd) {
async_call(function(){ hwnd(); myLib.flow_onward(g_flow[hwnd]["whendone"]); });
}
flow_onward(this.init);
};
// User of my library
myLib.init();
myLib.doStuff();
Doing this way you can ensure the sequentiality and expand the numbers of callback as much as you want.
ps: this code has not been tested
Related
I've looked through a few questions related to this error, and most of them seem to be a misunderstanding of what the keyword this means. I don't think I'm having that problem here. Mine might be some sort of circular dependency problem that I cannot articulate well enough to figure it out on my own.
I've tried to distill my problem into three files presented below.
something.js
var A = require('../lib/a');
var Something = function (type) {
this.type = type;
};
Something.prototype.setTemplate = function (template) {
this.template = template;
};
Something.prototype.applyTemplate = function () {
var templateResult = this.template.calculate();
};
var factory = {};
factory.createSomething = function(type) {
return new Something(type);
};
factory.createA = function (input) {
return A.Make(input);
};
module.exports = factory;
a.js
var S = require('../prof/something');
var _ = require('underscore');
var A = function (input) {
this.input = input;
};
A.prototype.calculate = function () {
var calculation = 0;
var _s = S.createSomething('hello world');
// do calculation using input
return calculation;
};
var factory = {};
factory.Make = function (input) {
var a = new A(input);
return a;
};
module.exports = factory;
a_test.js
describe('Unit: A Test', function() {
var S = require('../prof/something');
it('test 1', function() {
var a = S.createA({
//input
});
var s = S.createSomething('type1');
s.setTemplate(a);
s.applyTemplate(); // error
});
});
The error gets thrown from the top level in a_test.js on the line with the comment //error. At the lowest level, the 'is not a function ' error is thrown in a.js at the S.createSomething(type) method. It says that S.createSomething() is not a function.
I've put a breakpoint in at that line and tried to call functions from the underscore library, but it gives the same error. So it seems that the require statements inside a.js are not throwing errors, but none of the injected objects can be used to call functions from. The a_test.js file is being run with the karma library.
Am I violating some javascript paradigm by referencing back and forth between A and S? How can I do this properly?
Edit: I've done some further testing. It doesn't actually matter if the test file looks like this:
describe('Unit: A Test', function() {
var S = require('../prof/something');
it('test 1', function() {
var a = S.createA({
//input
});
a.calculate(); // error
});
});
An error is still thrown at the line indicated above.
The files in the question reference each other. This is called cyclic dependencies. The solution is to move the var S = require('../prof/something'); statement into the calculate function like so:
a.js
// move the line from here
var _ = require('underscore');
var A = function (input) {
this.input = input;
};
A.prototype.calculate = function () {
var S = require('../prof/something'); // to here
var calculation = 0;
var _s = S.createSomething('hello world');
// do calculation using input
return calculation;
};
var factory = {};
factory.Make = function (input) {
var a = new A(input);
return a;
};
module.exports = factory;
I need run several function parallel inside promise.then()
I tried to use code like bellow, but it work not correct:
function fadeElement(selector){
return function () {
return $(selector).fadeOut(400).promise();
}
}
function runParallel(owner, promises) {
return function () {
var differed = new $.Deferred();
var resolveDiffered = function () { differed.resolve(); };
$.when.apply(owner, promises).
then(resolveDiffered);
return differed.promise();
}
}
FormInput.prototype.ReloadPage = function(){
var firstOne = fadeElement('#element_Id_1');
var firstTwo = fadeElement('#element_Id_2');
var firstThree = fadeElement('#element_Id_3');
var secondOne = fadeElement('#element_Id_4');
var thirdOne = fadeElement('#element_Id_5');
var thirdTwo = fadeElement('#element_Id_6');
$.when(firstOne(), firstTwo(), firstThree())
.then(secondOne)
.then(
runParallel(this, [thirdOne(), thirdTwo()])
);
}
firstOne, firstTwo, firstThree, secondOne are runs without 400ms duration.
thirdOne, thirdTwo - not run at all.
I think I have a mistake in runParallel, but I havn't enough knowledge to understend where. I think so, becouse this code will work:
$.when(firstOne(), firstTwo(), firstThree())
.then(secondOne)
.then(thirdOne)
.then(thirdTwo);
The problem is that you were calling thirdOne and thirdTwo (and thus starting the fading process) when you passed those functions to runParallel:
.then(
runParallel(this, [thirdOne(), thirdTwo()])
);
Instead, you should remove the final () and pass functions to runParallel, which should map each method to the result of calling it. Changing the placement of when each promise-generating function is called will allow the fading process to be delayed until be after the other promises have completed:
function fadeElement(selector) {
return function() {
return $(selector).fadeOut(400).promise();
}
}
function runParallel(owner, promises) {
return function() {
return $.when.apply(owner, promises.map($.call, $.call))
}
}
FormInput.prototype.ReloadPage = function() {
var firstOne = fadeElement('#element_Id_1');
var firstTwo = fadeElement('#element_Id_2');
var firstThree = fadeElement('#element_Id_3');
var secondOne = fadeElement('#element_Id_4');
var thirdOne = fadeElement('#element_Id_5');
var thirdTwo = fadeElement('#element_Id_6');
$.when(firstOne(), firstTwo(), firstThree())
.then(secondOne)
.then(
runParallel(this, [thirdOne, thirdTwo])
);
}
function FormInput () {
}
new FormInput().ReloadPage()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="element_Id_1">1</div>
<div id="element_Id_2">2</div>
<div id="element_Id_3">3</div>
<div id="element_Id_4">4</div>
<div id="element_Id_5">5</div>
<div id="element_Id_6">6</div>
I have JavaScript class which have huge functions which are very difficult to maintain.
The 2 public functions are called at start and then on click. I want to create private functions inside these public functions say break into into some private functions scope to these public methods.
var searchResultView;
var SearchResultView = function () {
me = this;
this.init = function () {
// huge code
}
this.Search = function () {
// huge code
}
}
jQuery(function () {
searchResultView = new SearchResultView();
searchResultView.init();
searchResultView.Search();
}
What will best way to achieve this. I tried to use below approach but i think this nested function will not work well.
var searchResultView;
function searchResultView() {
me = this;
this.init = function () {
var declareControls = function () {}
var addEvents = function () {}
var fillControls = function () {}
declareControls();
addEvents();
fillControls();
}
this.Search = function () {
var validateAndCreateCriteria = function () {
if (!validateAandGetLocation()) {
alert("invalid location");
return false;
}
if (!validateAandGetCategory()) {
alert("choose search type");
return false;
}
var validateAandGetLocation = function () {}
var validateAandGetCategory = function () {}
}
validateAndCreateCriteria();
}
}
jQuery(function () {
searchResultView = new searchResultView();
searchResultView.init();
});
If I understood correctly, you should have the functions something like this:
var foo = (function() {
var privateBar = function() { // private function
},
privatefooBar = function() { // private function
};
return {
publicFoo : function() { //public function
/* use privateBar and privatefooBar functions here */
}
};
})();
Later you can access publicFoo function by using
foo.publicFoo();
But you can't access the inside functions which are privateBar() and privatefooBar() directly because they are private functions.
Updated Fiddle
Breaking up the function is easy:
function f(..) {
// many lines here
return ret_f;
}
if equivalent to
function f {
function f1(..) {
// not so many lines here
}
function f2(..) {
// not so many lines here
}
var ret_f1 = f1(..);
var ret_f2 = f2(..);
// calculate ret_f from ret_f1 and ret_f2
return ret_f;
}
or if you prefer this style using anonymous functions
function f {
var f1 = function(..) {
// not so many lines here
};
var f2 = function(..) {
// not so many lines here
};
var ret_f1 = f1(..);
var ret_f2 = f2(..);
// calculate ret_f from ret_f1 and ret_f2
return ret_f;
}
I fear however your real question is specific to your existing code and is about what useful smaller functions to extract there and how to combine them.
For this one would need to have your full code and understand it. That might be a bit much for this QA format.
I am trying to write a small javascript library as shown below. What I really want is when I call
console.log(tnd().pv);
it should output same number and not generate new number everytime. I know the issue is it calls Math.random everytime I console log. But how can I do so that it outputs same number?
(function () {
var tnd = function() {
return new tnlib();
};
var tnlib = function() {
this.version = function(){
console.log('1.0');
};
this.pv = Math.random()*10000000000000000;
};
if(!window.tnd) {
window.tnd = tnd;
}
})();
Don't execute Math.random() on each invocation of tnlib, but as a static variable:
(function () {
function tnd() {
return new tnlib();
}
function tnlib() {
}
tnlib.prototype.version = function(){
console.log('1.0');
};
tnlib.prototype.pv = Math.random()*10000000000000000;
if (!window.tnd) {
window.tnd = tnd;
}
}());
(or, if you really need to make pv an instance property):
var staticPv = Math.random()*10000000000000000;
function tnlib() {
this.pv = staticPv;
…
}
I want to make a class in javascript to reuse from my main code in the connection with an indexeddb object. What I have now is:
function DATABASE() {
this.DB_NAME = 'MYdatabase';
this.DB_VERSION = 1;
this.db = null;
this.results = null;
}
DATABASE.prototype.open = function(callback) {
var req = indexedDB.open(this.DB_NAME, this.DB_VERSION);
req.onsuccess = function (evt) {
this.db = this.result;
callback();
};
req.onerror = function (evt) {
console.error("openDb:", evt.target.errorCode);
};
req.onupgradeneeded = function (evt) {
console.log("openDb.onupgradeneeded");
};
}
My problem here is that when the onsuccess executes I loose the scope of my main class and this is not what I expected. How can I do what I am looking for?
I want to make some connections at the same time with this, something like:
var DB = new DATABASE();
DB.open(function(res){});
var DB2 = new DATABASE();
DB2.open(function(res){});
var DB3 = new DATABASE();
DB3.open(function(res){});
thanks so much.
Under var req add var self = this; and use like this whenever the scope changes:
self.db = self.result;
My problem here is that when the onsuccess executes I loose the scope of my main class and this is not what I expected.
It's not scope, but the value of this during a function call depends on how the function is called. So what's happening is that the functions you're assigning to req are getting called with this being a different value than it is in the call to open.
How can I do what I am looking for?
Since your functions already close over the scope of the call to open, the easiest way is to do what Andy suggested:
DATABASE.prototype.open = function(callback) {
var req = indexedDB.open(this.DB_NAME, this.DB_VERSION);
var self = this; // <=== New
req.onsuccess = function (evt) {
self.db = this.result; // <=== Changed
callback();
};
// ...
}
Note: In the changed line, I don't know what this.result is, so I don't know whether to change this to self there as well. It's entirely possible that you actually want this.result, if result is a property of the object that this points to on the callback.
More:
You must remember this
Closures are not complicated
Does this work for you? Putting the open function inside the DATABASE instead of on the prototype.
function DATABASE() {
var _this=this;
_this.DB_NAME = 'MYdatabase';
_this.DB_VERSION = 1;
_this.db = null;
_this.results = null;
_this.open = unction(callback) {
var req = indexedDB.open(_this.DB_NAME, _this.DB_VERSION);
req.onsuccess = function (evt) {
_this.db = _this.result;
callback();
};
req.onerror = function (evt) {
console.error("openDb:", evt.target.errorCode);
};
req.onupgradeneeded = function (evt) {
console.log("openDb.onupgradeneeded");
};
}
}
var that = this
req.onsuccess = function (evt) {
that.db = that.result;
callback();
};
Also I recommend to read this article: Scope and this in JavaScript