$.getJSON Callback Help - Not a Function - javascript

My context is as follows:
I have a variable 'qq' - I want to assign data to this variable from an API call, and once the data has been assigned, I then use this data in a paint/binding process.
The API call and assigning to var 'qq' works fine - but I cant seem to get my callback to work - I keep getting an error: callback() is not a function
This is what my code currently looks like:
var qq = [];
// binding function - to be run after data loader has completed
function sayIamDone() {
alert('I Am Done');
// do data bindings with qq
}
// load data from api into var qq
function dataLoader(inp,callback) {
let url = 'http://localhost:65232/api/layercolor/' + inp;
console.log(url);
$.getJSON(url,function(result) {
qq = eval('({' + result + '})');
//console.log(qq);
callback();
});
}
// call data loader
dataLoader('Prov', sayIamDone());
From the above I get the following error in my chrome console:
Uncaught TypeError: callback is not a function
I have tried the following - which seems to work:
dataLoader('Prov', function () { alert('I Am Done');});
but it is not ideal in my context, as I want to call dataLoader('Prov',XXX()) where XXX() could be a number of different functions using the newly loaded values in qq
Any suggestions as to where I am missing the boat please?

By running dataLoader('Prov', sayIamDone()); you are passing to dataLoader the result of sayIamDone function. You have to pass it without parenthesis in order to pass the function itself.
dataLoader('Prov', sayIamDone);

change:
dataLoader('Prov', sayIamDone());
to
dataLoader('Prov', sayIamDone);
because:
sayIamDone is function ,sayIamDone() is the result of function.Normally, sayIamDone() is undefined or return value in the sayIamDone;
want to use arguments?you can do this:
dataLoader('Prov', callFunc(n));
function callFunc(arg) {
return function() {
sayIamDone(arg);
};
}
or more arguments?you can do this by spread
dataLoader('Prov', callFunc(n));
function callFunc(...arg) {
return function() {
sayIamDone.apply(null, arg);
};
}

Related

How do i use a value from a function in another as a callback? Node js

I´ve been making a prototype of webservice and I get confronted with the following problem: Whenever I try to use a 'var' as a callback i get: undefined.
What I'm tryng to do is:
var mysqlquery = function (){
var vAlue = XXX;
}
var service = function (pp, ee, cb){
var toReturn= ({ //XML code
Value: vAlue
})
cb(toReturn);
};
Output should be XXX
The service runs fine and logs the values, but when i try to make it a callback to respond it is undefined, I guess because of the async of node.
Already tried making it a global or global.window or calling it inside another function, none of wich work. I don´t want to use extra modules for this, is there any method for it ? (Also tried this.)
Any tip is much apreciated, thanks.
You already know that defining a var in a function limits its scope to that function, but you can pass that data out of the function using a return, like so:
var mysqlquery = function (){
return 'XXX';
}
console.log(mysqlquery())
> "XXX"
What's happening in the console.log line is that your function is being evaluated, and returns "XXX", and then it is passed to console.log.
This is the foundation of callbacks: if you have an asynchronous function, you can pass a callback function into it to feed in the result of the async function:
function print(res) {
console.log(res)
}
function asyncThing(cb) {
var ten = 5 + 5
window.setTimeout(cb.bind(this, ten), 5000)
}
asyncThing(print)
... [wait five seconds]...
> 10

json after success return undefined

I am using JS with Angular came to the following problem.
I am getting data from a requestService, so a call the request function and then do something with the data in a 'success' function. Inside this function, everything is fine and I get all my results but as soon as a leave the success function, my results are undefined. I read some other questions/answers about similar problems, and tried other things. However I do not really know how to hand this and wanted to ask this explicitly with a code example:
function loadShips() {
var count = 0;
RequestService.getShips(nelat, swlat, nelong, swlong, timestamp)
.success(function(results) {
var groupedShips = results.aisData.aisGroupedByShipType;
_.each(groupedShips, function(groupedShip) {
_.each(groupedShip, function(ship) {
Markers['marker' + count] = createMarker(ship);
count++;
});
});
console.log(Markers, '#1')
return Markers
});
console.log(Markers, '#2');
return Markers;
}
So anyone could maybe tell me, why Markers at the print out of '#1' are defined and at '#2' are undefined.
Assuming the request is being done asynchronously, the call at #2 is happening before the request's success method is being called. This would explain why the object does not exist yet.
One solution would be to pass a call back method into the factory as a parameter, and then call that method after the request success has occurred. That would look something like this:
function loadShips(callBack) {
var count = 0;
RequestService.getShips(nelat, swlat, nelong, swlong, timestamp)
.success(function(results) {
var groupedShips = results.aisData.aisGroupedByShipType;
_.each(groupedShips, function(groupedShip) {
_.each(groupedShip, function(ship) {
Markers['marker' + count] = createMarker(ship);
count++;
});
});
console.log(Markers, "#1");
callBack(Markers);
});
}
Using this method looks like this:
function myCallback(markers){
console.log(markers, "#2");
//assign markers to something
}
loadShips(myCallback);
As Will P pointed out, with asynchronous functions, the inline code after them will execute first, because the success function is still waiting in the event queue.
in addition to that, Markers is being returned from inside a anonymous function which will not return it as the result of loadShips but will return it inside ajax wonderland, never to be seen.
what you will have to do is have a function that receives the data when it is ready and call that function with the data. I'm assuming things happen after the ships load, those things will have to be called after the anonymous function is done creating Markers.
function loadShips() {
var count = 0;
RequestService.getShips(nelat, swlat, nelong, swlong, timestamp)
.success(function(results) {
var groupedShips = results.aisData.aisGroupedByShipType;
_.each(groupedShips, function(groupedShip) {
_.each(groupedShip, function(ship) {
Markers['marker' + count] = createMarker(ship);
count++;
});
});
doFancyWonderfulThingsInTheOcean(Markers);
});
}

New to Javascript - Callback issue

I am new to Javascript programming coming from a Java and Objective C background. I am looking to learn a bit more about Javascript for hybrid mobile applications.
In doing so I am trying to do a login with a call back but I am having a little trouble understanding both the syntax and the way a callback works.
First up I am calling the following login function which just creates an ajax call to fetch some JSON at the minute for testing purposes:
testLogin.loginWithUsername ("test", loginCallback);
This works OK as I can see the 200 OK Status and the expected JSON in logging.
However the call back "loginCallBack" never gets called.
It is as follows:
loginCallback: {
success: function(id) {
alert ('success');
}
failure: function (id, error) {
alert ('failure');
}
}
First off the above gives me a syntax error when I try to run the code, at the success:function(id) line. I can change it and the failure function to = function(id) and it the code runs then but the callback is never called.
I am using a library for the login that states the call back required is an object that needs a success and failure function and the code above is the given example.
So first off I don't understand why the above syntax works in the sample code but gives me an error when I run it?
Secondly am I calling the callback correctly? Both the loginWithUsername call and the loginCallback function are in the same Login.js file.
Here is an example how callback works:
First thing: you need to create a new object containing your functions/methods. Properties and methods are listed comma seperated.
// Creating new object with callback functions
var loginCallback = {
success: function(id) {
alert ('success');
} , // Add a comma
failure: function (id, error) {
alert ('failure');
}
}
function loginWithUsername(username, callback) {
if (username === 'test') {
var successId = 1;
callback.success(successId);
} else {
var errorId, errorMsg;
errorId = 0;
errorMsg = 'Error';
callback.failure(errorId, errorMsg);
}
}
Now you can call the function:
loginWithUsername('test', loginCallback);
And the result should be 'success'.
Edit:
But you can do this without an object, by passing the function directly:
// Creating function
function showMessage(message) {
alert(message);
}
function loginWithUsername(username, callback) {
if (username === 'test') {
callback('success');
} else {
callback('failure');
}
}
// Pass function
loginWithUsername('test', showMessage); // Result: 'success'
loginWithUsername('abcd', showMessage); // Result: 'failure'
First off the above gives me a syntax error when I try to run the code, at the success:function(id) line.
Each property: value pair in an object literal must be separated with a comma.
}, /* Your comma is missing which is why you get a syntax error */
failure:
This:
loginCallback: {
is only acceptable if you want to define a property inside an object literal.
This:
testLogin.loginWithUsername ("test", loginCallback);
is using a variable.
You probably want:
var loginCallback = {
but it is hard to tell without more context.

Howto get a callback on JS function execution using a Spy

I want to spy on a function, then execute a callback upon function completion/initial call.
The following is a bit simplistic, but shows what I need to accomplish:
//send a spy to report on the soviet.GoldenEye method function
var james_bond = sinon.spy(soviet, "GoldenEye");
//tell M about the superWeapon getting fired via satellite phone
james_bond.callAfterExecution({
console.log("The function got called! Evacuate London!");
console.log(test.args);
});
Is it possible to do this in Sinon? Alternate libraries welcome as well if they solve my problem :)
It's clunky but you can:
//send a spy to report on the soviet.GoldenEye method function
var originalGoldenEye = soviet.GoldenEye;
var james_bond = sinon.stub(soviet, "GoldenEye", function () {
var result = originalGoldenEye.apply(soviet, arguments);
//tell M about the superWeapon getting fired via satellite phone
console.log("The function got called! Evacuate London!");
console.log(arguments);
return result;
});
You have to stub the function. From the docs:
stub.callsArg(index);
Causes the stub to call the argument at the
provided index as a callback function. stub.callsArg(0); causes the
stub to call the first argument as a callback.
var a = {
b: function (callback){
callback();
console.log('test')
}
}
sinon.stub(a, 'b').callsArg(0)
var callback = sinon.spy()
a.b(callback)
expect(callback).toHaveBeenCalled()
//note that nothing was logged into the console, as the function was stubbed

Passing Params to a Window[callback] Function

I have some code that requests some JSON from an API. When data is returned, per the documentation, it sends back a callback function that is to be used to parse the data at the top level. After the call is made, I have the following code to capture the data and process it:
var callback = 'functionUsedInApiCall';
window[callback] = newCallBackFunction;
How would I go about passing custom params to the callback function above as the data is being returned?
In order to capture the data, I must write the callback function like this:
function newCallBackFunction(root) {
//root is the data
}
Any help would be greatly appreciated.
Are you talking about JSONP? If so, you don't call the callback or pass in the argument at all, the code returned by the API does.
E.g., your code:
window.myCallback = newCallbackFunction;
function newCallbackFunction(data) {
// use the data
}
(I'm assuming this isn't at global scope, hence assigning to the window object.)
...plus your code for initiating the JSONP call, which is usually appending a script element to your page with a URL containing the name of the callback ("myCallback" in the above).
Their response will look like this:
myCallback({
// data here
});
...which, when it arrives, will run (because it's the content of a script element), and will call your function. This is how JSONP works.
If you want to include further arguments for the function, all you do is have the callback they call turn around and call your target function, e.g.:
window.myCallback = function(data) {
newCallbackFunction(data, "foo", "bar");
};
function newCallbackFunction(data) {
// use the data
}
Now when their code calls the global myCallback, all it does is turn around and call newCallbackFunction with that data and the arguments you specify.
Those arguments don't have to be literals as in the above. Here's an example with a bit more context, using a closure:
// Assume the url already contains the name of the callback "myCallback"
function doJSONP(url, niftyInfo, moreNiftyInfo) {
var script;
// Set up the callback
window.myCallback = function(data) {
// Runs when the data arrives
newCallbackFunction(data, niftyInfo, moreNiftyInfo);
};
// Trigger the request
script = document.createElement('script');
script.src = url;
document.documentElement.appendChild(script);
}
Ideally, though, when doing JSONP you auto-generate the name of the callback each time so that it's specific to the request (in case you have two outstanding requests at the same time):
// Assume the url ends with "callback=" and we append the name of the
// callback function to it
function doJSONP(url, niftyInfo, moreNiftyInfo) {
var cbname, script;
// Get a callback name
cbname = "callback_" +
new Date().getTime() +
"_" +
Math.floor(Math.random() * 10000);
// Set up the callback
window[cbname] = function(data) {
// Remove us from the window object
try {
delete window[cbname];
}
catch (e) { // Handle IE bug (throws an error when you try to delete window properties)
window[cbname] = undefined;
}
// Runs the function
newCallbackFunction(data, niftyInfo, moreNiftyInfo);
};
// Trigger the request
script = document.createElement('script');
script.src = url + encodeURIComponent(cbname);
document.documentElement.appendChild(script);
}
Parameters in javascript are passed as an Array, so you can pass the parameters you need, or even complete functions that will add per case functionality in your callback.
You could do the following:
function newCallBackFunction(root /*your data*/, paramsHash /*a hash array with optional parameters*/)
{
//if arg1 can be found in the hash
if( paramsHash['arg1'] ]
{
//do something that requires arg1
}
else if( paramsHash['arg2'] )
{
//do something that requires arg2
}
return root;
}
And in your main code:
var hash = new Array();
hash['arg1'] = 'str1';
hash['arg2'] = 1;
hash['arg3'] = new Car(); //or any other object you want
It is also possible to just declare some parameters and supply them to your function only when needed:
function newCallBackFunction(root, param1, param2)
{
if( param1 ) { /* similar to first example */ }
}
Or finally just pass whatever parameter you want and read them from the arguments table
function newCallBackFunction(root)
{
for( int i = 1; i < arguments.length; i++ )
//do something with the parameters you pass beside root
}
And in main code:
newCallBackFunction( root, param1, param2, param3 );
I hope I covered you!

Categories

Resources