Passing a variable from a function back to a function in Dojo - javascript

I have a question. My intervalValue in the start function is undefined. But in the microflow function it is the value I want to have. How can I return the value in the microflow function back to the start function. I have tried basic global and return implementations of javascript, but that doesn't work and the dojo.global isn't clear enough for me know how to implement. All help is appreciated. See my code below:
start : function() {
this.addOnLoad(dojo.hitch(this, function() { //make sure the thing only starts when completely loaded!
if (this.once)
this.handle = window.setTimeout(dojo.hitch(this, function() {
this.intervalexecute();
console.log("addOnLoad " + this.intervalValue);
this.execute();
this.stopped = true;
}), this.intervalValue);
else {
this.intervalexecute();
console.log("addOnLoad " + this.intervalValue);
if (this.startatonce)
this.execute(); //invoke directly as well
this.handle = window.setInterval(dojo.hitch(this, this.execute), this.intervalValue);
}
}));
},
intervalexecute : function() {
if (this.dataobject != null && this.dataobject.getGUID && this.dataobject.getGUID())
{
//microflow set, not already calling a microflow
mx.processor.xasAction({
error : function() {
logger.error(this.id + "error: XAS error executing microflow");
},
actionname : this.intervalmicroflow,
applyto : 'selection',
guids : [this.dataobject.getGUID()],
callback : dojo.hitch(this, this.microflowresult)
});
}
},
microflowresult: function(result) {
if (result) {
this.intervalValue = dojo.fromJson(dojo.isIE ? result.xhr.responseText : result.xhr.response).actionResult;
console.log("result: " + this.intervalValue);
}
},

The reason interval value is not set is because microflowresult is an asynchronous function. Your logging statement in start is executed before microflowresult is called.
You need to have your callback do any processing on intervalValue.

Related

Access function in module with similar name of function in another module

Code:
for (var i in RESTCalls_GET) {
describe('Retrieve all Product Component names and their IDs', function() {
var restCalls;
beforeEach(function() {
RESTCalls_GET.setClient(mockClient);
restCalls = new Rest_calls(mockClient);
});
describe(i + '()', function() {
it('should return data if response code is 200', function(done) {
mockClient.mockURLForSucceed(eval('restCalls.' + i + "_RESTCall"), eval('RESTCalls_GET_ExampleData.' + i + "_ExampleData"), 200);
eval('RESTCalls_GET.' + i)(function(result) {
result.should.equal(eval('RESTCalls_GET_ExampleData.' + i + "_ExampleData"));
done();
});
}),
it('should return error if response code is NOT 200', function(done) {
mockClient.mockURLForError(eval('restCalls.' + i + "_RESTCall"), null, TestData.RESTCallResponseError_Test);
eval('RESTCalls_GET.' + i)(function(errorObj) {
errorObj.should.have.property('errorCode');
done();
});
});
});
});
}
I am looping though functions in RESTCalls_GET. Say, for example, i = getComponent, a function called getComponent_RESTCall will be in module restCalls
I have been told that one way to accomplish this is by using eval() (even though it is not recommended). This way is not working and when I debug, the parameters which use eval() in mockURLForSucceed are undefined.
This obviously causes all my tests to fail.
Any suggestions appreciated.
EDIT: (additional information)
var mockClient = function() {
var urlMap = {};
return {
get: function(url, callback) {
var entry = urlMap[url];
if (entry) {
callback(entry[0], entry[1]);
} else {
console.error("Unable to match URL " + url);
}
return {
on: function() {
//Ignore
}
};
},
mockURLForSucceed: function(URLofRESTCall, succeedData, succeedRes) {
urlMap[URLofRESTCall] = [succeedData, {statusCode: succeedRes}];
},
mockURLForError: function(URLofRESTCall, errorData, errorRes) {
urlMap[URLofRESTCall] = [errorData, errorRes];
}
}
}();
EDIT: (half way there)
I've resorted back to eval() an got the function/variable name required in format file.functionName by this:
var RESTCallURL = eval('"restCalls." + i + "_RESTCall"');
var RESTCallData = eval('"RESTCalls_GET_ExampleData." + i + "_ExampleData"');
The problem I'm having now if that these are strings. So when I pass them into a function, it gets that string value and not the one it equals in it's own function, does that make sense?
What I mean is that if I passed in RESTCallURL into a function now, then the value of that parameter would be restCalls.whatever_RESTCall whereas before it got the URL of the REST Call I am calling (http://whatever). Since I now have the name of the function, am I able to search for functions in my project by that name?
This task seems so simple to do and I think I am over thinking it.
I don't think you need eval there, what about using
RESTCalls_GET[i](function(result) {
result.should.equal(RESTCalls_GET_ExampleData[i + '_ExampleData']));
done();
});
You could easily test this behaviour by defining the following in your browser console
var test = {
'some-function': function() { console.log('works'); }
};
test['some-function']();

Prevent require.js to log itself to console

When I run this code in Chrome DevTool,
require(['common'], function (common) { common.getProfilPic(123); })
It always print the whole chunk of requirejs code,
function localRequire(deps, callback, errback) {
var id, map, requireMod;
if (options.enableBuildCallback && callback && isFunction(callback)) {
callback.__requireJsBuild = true;
}
if (typeof deps === 'string') {
if (isFunction(callback)) {
//Invalid call
return onError(makeError('requireargs', 'Invalid require call'), errback);
}
//If require|exports|module are requested, get the
//value for them from the special handlers. Caveat:
//this only works while module is being defined.
if (relMap && hasProp(handlers, deps)) {
return handlers[deps](registry[relMap.id]);
}
//Synchronous access to one module. If require.get is
//available (as in the Node adapter), prefer that.
if (req.get) {
return req.get(context, deps, relMap, localRequire);
}
//Normalize module name, if it contains . or ..
map = makeModuleMap(deps, relMap, false, true);
id = map.id;
if (!hasProp(defined, id)) {
return onError(makeError('notloaded', 'Module name "' +
id +
'" has not been loaded yet for context: ' +
contextName +
(relMap ? '' : '. Use require([])')));
}
return defined[id];
}
//Grab defines waiting in the global queue.
intakeDefines();
//Mark all the dependencies as needing to be loaded.
context.nextTick(function () {
//Some defines could have been added since the
//require call, collect them.
intakeDefines();
requireMod = getModule(makeModuleMap(null, relMap));
//Store if map config should be applied to this require
//call for dependencies.
requireMod.skipMap = options.skipMap;
requireMod.init(deps, callback, errback, {
enabled: true
});
checkLoaded();
});
return localRequire;
} require.js:1361
require(['common'], function (common) { console.log(common.getProfilPic(123)); })
function localRequire(deps, callback, errback) {
var id, map, requireMod;
if (options.enableBuildCallback && callback && isFunction(callback)) {
callback.__requireJsBuild = true;
}
if (typeof deps === 'string') {
if (isFunction(callback)) {
//Invalid call
return onError(makeError('requireargs', 'Invalid require call'), errback);
}
//If require|exports|module are requested, get the
//value for them from the special handlers. Caveat:
//this only works while module is being defined.
if (relMap && hasProp(handlers, deps)) {
return handlers[deps](registry[relMap.id]);
}
//Synchronous access to one module. If require.get is
//available (as in the Node adapter), prefer that.
if (req.get) {
return req.get(context, deps, relMap, localRequire);
}
//Normalize module name, if it contains . or ..
map = makeModuleMap(deps, relMap, false, true);
id = map.id;
if (!hasProp(defined, id)) {
return onError(makeError('notloaded', 'Module name "' +
id +
'" has not been loaded yet for context: ' +
contextName +
(relMap ? '' : '. Use require([])')));
}
return defined[id];
}
//Grab defines waiting in the global queue.
intakeDefines();
//Mark all the dependencies as needing to be loaded.
context.nextTick(function () {
//Some defines could have been added since the
//require call, collect them.
intakeDefines();
requireMod = getModule(makeModuleMap(null, relMap));
//Store if map config should be applied to this require
//call for dependencies.
requireMod.skipMap = options.skipMap;
requireMod.init(deps, callback, errback, {
enabled: true
});
checkLoaded();
});
return localRequire;
}
and and me from seeing the log result, and idea how to stop requirejs to print itself?
Run this instead:
(function(){ require(['common'], function (common) { common.getProfilPic(123); }) })()
What happens is that the console is printing out the value of the expression. The value of a function call is what the call returns. You can easily work around it with something like:
require(['common'], function (common) { common.getProfilPic(123); }); 1
Adding ; 1 will make the expression evaluate to 1. So you'll get 1 on the console but at least it won't push diagnostic messages off the screen.

Anonymous function causing ids to not be set after AJAX success

I'm making an AJAX call from within an Anonymous function. When the success callback takes place I'm then able to set my custom JS objects ids and other important info that has arrived from the data server.
After I set the a.target.id to the returned data.id everything looks fine.
On the step where I'm calling a function to do some work with the newly updated custom JS object, that I just updated with the response data from the server. I am passing the parent of that object to the method to do some work on all the children of that object.
However, as you can see on the last example in the snap shot photos the a.target.parent.children[0].id is not in the collection and/or it's ids where never set.
I must be losing a reference to that object during the AJAX call when using an Anonymous function.
Here is all of the code. How am I losing the reference? Or how can I maintain a reference to that parent's children when the AJAX call returns?
I've never had this happen before, makes me believe that it has something to do with the Anonymous function.
var horizontalPositioner = function (horizontals) {
var hpa = ['?horPositions='];
for (var i = 0; i < horizontals.children.length; i += 1) {
hpa.push(horizontals.children[i].id + ':' + horizontals.children[i].position + ',');
};
hpa[i] = hpa[i].replace(',', '');
dataBase.update(dbPart('horizontal' + hpa.join('')));
};
this.subscribe.call(this, e.horizontaladded, function (a, fn) {
//
if (!a.extra.owner.id) {
return;
};
(function (a) {
dataBase.insert(
dbPart(
['horizontal?a=', a.extra.owner.instanceName, '&id=', a.extra.owner.id].join(''),
a.target
),
dbCB(
function (data, status) {
if (status === 'error') { return; };
a.target.id = data.id,
a.target.HTML().addClass('alum_' + data.id),
a.target.finish.id = data.finishID,
a.target.size.id = data.sizeID,
a.target.siteLine.id = data.sitelineID;
//
//reposition horizontals
// setTimeout(function () { horizontalPositioner(a.target.parent); }, 1000);
debugger
horizontalPositioner(a.target.parent);
if (fn) { processCallbacks(data, status, fn); };
//very last
events.publishDatabaseCallbacks(e.horizontaladded,
eArgs(a.bay, { data: data, instanceName: 'horizontal', ownerid: a.extra.owner.id, id: data.id }));
},
function (xhr, status, errorThrown) { console.log('ERROR adding horizontal'); })
);
}(a));
}, true);
I've added an anonymous function with a nested setTimeout to give everything time to build. I've got many events taking place at once, so for now this works.
var horizontalPositioner = function (horizontals) {
(function (hors) {
setTimeout(function () {
var hpa = ['?horPositions='];
for (var i = 0; i < hors.children.length; i += 1) {
hpa.push(hors.children[i].id + ':' + (hors.children[i].position ? hors.children[i].position : 1) + ',');
};
hpa[i] = hpa[i].replace(',', '');
dataBase.update(dbPart('horizontal' + hpa.join('')));
}, 1000);
}(horizontals));
};

Getting UnreadmessagesCount

The question I have here is for some reason when the getInboxUnreadMessagesCount js function is ran then it comes up with a different number then what is there to begin with and keep in mind there is no new message being sent. When I run the php dashboard functions they both are returning the correct numbers but I think the issue lies with the last line of code with the messageTimer
Anybody even have any thoughts onto what it might be? I'm hoping someone can figure it out.
var $messageCountJSON;
var messageTimer = '';
var messageInterval = 5;
//assumed JSON response is {"count":"20"} for example sake.
function getInboxUnreadMessagesCount(displayElementID) {
$.get('dashboard/getInboxUnreadMessagesCount', function (data) {
$messageCountJSON = data;
}, 'json');
if (displayElementID != null && displayElementID != undefined && displayElementID != '') {
//$('#'+displayElementID).html($messageCountJSON);
if (parseInt($('#' + displayElementID).text()) < parseInt($messageCountJSON)) {
$.jGrowl("You have received a new private message!", { theme: 'information' });
$('#' + displayElementID).html($messageCountJSON).css({ "display": "block" });
}
if (parseInt($messageCountJSON) == 0) {
$('#' + displayElementID).html($messageCountJSON).css({ "display": "none" });
}
}
}
function getInboxMessagesCount(displayElementID) {
$.get('dashboard/getInboxMessagesCount', function (data) {
$messageCountJSON = data;
}, 'json');
if (displayElementID != null && displayElementID != undefined && displayElementID != '') {
//$('#'+displayElementID).html($messageCountJSON);
if (parseInt($('#' + displayElementID).text()) < parseInt($messageCountJSON)) {
$('#' + displayElementID).html($messageCountJSON);
}
if (parseInt($messageCountJSON) == 0) {
$('#' + displayElementID).html($messageCountJSON);
}
}
}
$(document).ready(function () {
messageTimer = setInterval(function () { getInboxUnreadMessagesCount('notifications'); getInboxMessagesCount('inboxCount'); }, messageInterval * 1000);
});
//you can optionally kill the timed interval with something like
//$('#pmMessagesIcon').click(function(){clearInterval(messageTimer);})
You are trying to access the message count before it's received:
// Here you create an asynchronous request to the server.
$.get('dashboard/getInboxUnreadMessagesCount', function (data) {
// This section of your code will only run after you get the JSON response
$messageCountJSON = data;
}, 'json');
// Code here will run immediately after the request is fired,
// and probably before the JSON response arrives
You have to move your big if statements to inside each $.get() callback function.

Ajax.Request of prototype framework hangs with multiple calls to jsp page

I have a problem concerning multiple ajax requests using prototype.js version 1.7.
Here is the function I wrote to make the ajax call:
function checkClonability(element) {
var strUrl = "/dssweb/js/ajaxdbdispatcher";
var rowIndex = element.id.split('_')[1];
var tabschema = $('tabschema_' + rowIndex).innerHTML.trim();
var tabname = $('tabname_' + rowIndex).innerHTML.trim();
var op = <%=AjaxDbDispatcher.CLONE_TABLE_COMPARE%>;
workLevel(rowIndex, 'run');
var qb = new QueryStringBuilder();
qb.addParameter('op', op);
qb.addParameter('dbsource', 'UAT');
qb.addParameter('dbtarget', 'PROD');
qb.addParameter('tabschema', tabschema);
qb.addParameter('tabname', tabname);
new Ajax.Request(strUrl, {
method:'post',
asynchronous: true,
parameters: qb.toString(),
onSuccess: function(transport){
var json = transport.responseText.evalJSON();
if(json.equals) {
workLevel(rowIndex, 'ok');
element.onclick = '';
} else {
element.checked = false;
element.disabled = true;
workLevel(rowIndex, 'ko', 'La tabella ha un tracciato diverso in produzione!');
}
},
onFailure: function(err){
workLevel(rowIndex, 'none', 'Si è verificato un errore durante la verifica.');
}
});
}
The strUrl is a java servlet that makes a comparison of a database table between two different environments.
My page shows a list of tables and checkboxes to select them.
The function is fired by an onclick event on a checkbox. Everything works fine for a single call, but it hangs if I try to check several checkboxes without waiting for the end of the first call.
I tried it on chrome 8 and IE6 and I'm working on apache tomcat 6.
Any help would be apreciated.
when a user click two times quickly, the ajax request is send twice. Put some variable and a test on it that will stop a second execution if the ajax call hasnt ended:
var running = true;
function clickHandler() {
if (running) return;
running = true;
/** Some stuff here ***/
new Ajax.Request(strUrl, {
method:'post',
asynchronous: true,
parameters: qb.toString(),
onSuccess: function(transport){
var json = transport.responseText.evalJSON();
if(json.equals) {
workLevel(rowIndex, 'ok');
element.onclick = '';
} else {
element.checked = false;
element.disabled = true;
workLevel(rowIndex, 'ko', 'La tabella ha un tracciato diverso in produzione!');
}
},
onFailure: function(err){
workLevel(rowIndex, 'none', 'Si è verificato un errore durante la verifica.');
},
onComplete: function() { running = false; }
});
}
NB: note sure about the onComplete callback, check the manuals to be sure running will be set false whenever the ajax call ends.
Ok, I think I've solved my problem with this 'workaround' class.
It syncronizes calls and make them sequential:
var Syncro = Class.create(
{
initialize: function(params) {
// Check for Prototype class
if(typeof Prototype=='undefined') {
throw("JSSyncro requires the Prototype JavaScript framework to run.");
}
//handle input parameters
this.delay = (typeof params.delay == 'undefined' ? 1000 : params.delay);
this.allowDuplicates = (
typeof params.allowDuplicates=='undefined' || typeof params.allowDuplicates!='boolean'
? true : params.allowDuplicates);
this.order = (
typeof params.order=='undefined' || ['fifo','lifo'].indexOf(params.order)==-1
? 'fifo' : params.order);
this.operations = [];
this.terminated = true;
// private - check for duplicate operations in the stack
this.alreadyExists = function(operation) {
var exists = false;
this.operations.each(
function(element) {
if(element.toString()==operation.toString()) {
exists = true;
return;
}
}
);
return exists;
};
//private - run operations sequentially
this.runSyncronized = function() {
function nextTimeout(instance) {
setTimeout(
function(){
instance.runSyncronized();
},
this.delay);
}
if(this.operations.length>0) {
if(this.terminated) {
this.terminated = false;
var cmd = (this.order=='fifo'
? this.operations.shift() : this.operations.pop());
cmd();
} else {
nextTimeout(this);
}
} else {
this.terminated = true;
}
};
},
// public - wakeup the executor and run the following operation if the previous is terminated
setTerminated: function(boolValue) {
this.terminated = boolValue;
},
// public - set the operation to execute sequentially
execute: function(operation) {
if(this.allowDuplicates || !this.alreadyExists(operation)) {
this.operations.push(operation);
this.runSyncronized();
}
}
}
);
Syncro class has two main methods:
execute - where you can pass the function you must execute inside an anonymous function
setTerminated - a setter method useful to set that an asyncronous operation has terminated (i.e. set in the onComplete method the async call done with ajax).
checkboxClick function is obviously called in the onclick event of my checkboxes.
Hope this could be useful.
Bye.
Just an evolution in the constructor.
Initial parameters (passed in the constructor) are defined in an array:
new Syncro({[delay:1000][, allowDuplicates:true|false][, order:'lifo'|'fifo']});

Categories

Resources