How can I pass results from a callback via an object? - javascript

I am performing a Google local search, and wish to return the lat/long via an object.
The Google search itself works fine.
When inspected (using console.log or alert()) in the object itself, the results field appears to be populated OK.
However, when inspecting the instance of the object (instantiated before running the callback) the result is blank. I'm aware I don't need the accessor function - the end result is the same either way.
Is there something fundamental missing here? Thanks!
function GeoSearch() {
this.results = [];
this.searchComplete = function(localSearch) {
if(localSearch.results[0]) {
var resultLat = localSearch.results[0].lat;
var resultLng = localSearch.results[0].lng;
this.results = localSearch.results[0].lat;
}
}
this.getResults = function() {
return this.results;
}
}
function populateCoords(postcode) {
var localSearch = new google.search.LocalSearch();
var gs = new GeoSearch();
localSearch.setSearchCompleteCallback(gs, gs.searchComplete, [localSearch]);
localSearch.execute(postcode + ", UK");
alert(gs.getResults());
}

When you reference the function gs.searchComplete, you're detaching the method from the object it belongs to. Switch it to function () { gs.searchComplete(); }

Related

Using function of an object after grabbing it from array

When I try to grab the object from the array, the type is undefined. Therefore I cannot use a method from the undefined object as it doesn't exist. I am relatively new to JavaScript and I have come straight from Java so the way of retrieving objects is kind of new to me. This is what I currently have.
var fleetAmount = 0;
var fleets = [];
function Fleet(number) {
this.number = number;
this.activities = [];
this.addActivity = function (activity) {
this.activities.push(activity);
};
fleets.push(this);
}
var getFleet = function(fleetNumber) {
return fleets[fleetAmount - fleetNumber];
}
This is where I try to grab the object and preform the function
const Fl = require(‘fleet.js’);
const fleet = Fl.getFleet(fleetNumber);
fleet.addActivity(activity);
I am also working in Node.js, which is how I am using the require method.
In combination with the answer from #audzzy I changed the getFleet() function so that it would be more efficient. I tested it out and it worked. This is what I used
function getFleet(fleetNumber) {
let result = fleets.filter(function (e) {
return e.number = fleetNumber;
})
return result[0];
}
Thanks for the help! I appreciate it.
you want to create a new fleet object and add it, not "this"..
adding "this" would cause a circular reference, where
this.fleets[i] = this (and all fleets would have the same value)
when calling get fleet, I would check that a fleet was returned from get fleet
in case amount is less than the number you send to getFleet (where according to what you posted: 1 returns the last, 2 returns second to last etc..)..
I hope this explanation makes sense.. anyways, this should work..
var fleets = [];
doStuff();
function doStuff(){
addFleet(1);
addFleet(2);
addFleet(7);
addFleet(3);
// should return null
let fleet1 = getFleetByNumber(5);
// should return the fleet with number 7, and not change the fleet with number 1
let fleet2 = getFleetByNumber(7);
if(fleet2){
fleet2.addActivity("activity");
}
console.log(`fleets: ${JSON.stringify(fleets)} \nfleet1: ${JSON.stringify(fleet1)} \nfleet2: ${JSON.stringify(fleet2)}`);
}
function addFleet(number) {
let fleet = { number: number,
activities: [] };
fleet.addActivity = function (activity) {
this.activities.push(activity);
};
fleets.push(fleet);
}
function getFleetByNumber(fleetNumber) {
return fleets.find(function (e) {
return e.number == fleetNumber;
});
}
function getFleet(fleetNumber) {
let result = null;
if(fleets.length - fleetNumber >= 0){
result = fleets[fleets.length - fleetNumber];
}
return result;
}

How do we return function using module.exports in nodeJS?

How do we return function using module.exports in nodeJS?
file_1 book.js
module.exports = function() {
var points = 0;
return {
rate: function(value) {
points = value;
},
get: function() {
return points;
}
}
}
book.js is root file. We create two different instances but can not get the methods of root to script.js file.
file_2 main.js
var bA = require('./book.js');
var bB = require('./book.js');
bB.rate(10);
bB.get();
Output => can not find rate and get method.
Because the function returns an object with references to the rate and get functions, you need to execute it with a () on require like so:
var book = require('./book.js')();
book.rate(10);
book.get();
You're returning a function which returns an object.
Call the function and get the object
/*file_2 main.js*/
var bA = require('./book.js')();
var bB = require('./book.js')();
bB.rate(10);
bB.get();
Just in case if someone's facing same problem as me
I had something issue with my code. Lately realised I was making some API call and so return returned an object before fetching the value from API endpoint
I added async in front of function call and it worked!
var util=require('./app/Utils')
const url=await util.getInfo();
You can also provide a name to your anonymous export function as
module.exports.myfun = function() {
var points = 0;
return {
rate: function(value) {
points = value;
},
get: function() {
return points;
}
} }
Then use the function in another file as
var inc = require('./comp.js');
var mod = inc.myfun();
mod.rate(10);
console.log(mod.get());
In this way you don't need to have '()' at the time of required, though that option can also be used

JavaScript: Not Calling Constructor Function

Can someone shed some light as to why this doesn't work the way I think it should (or what I'm overlooking).
function Pane(data) {
var state = {
show: function(data) {
var pane = document.querySelector('.pane[data-content='+data.target+']');
pane.classList.add('active');
},
hide: function(data) {
var pane = document.querySelector('.pane[data-content='+data.target+']');
var paneSibling = $(pane.parentNode.childNodes);
paneSibling.each(function(sibling) {
if(check.isElement(sibling)) {
var isActive = sibling.classList.contains('active');
if(sibling != pane && isActive) {
sibling.classList.remove('active');
};
};
});
}
}
return state;
}
So I can console log Pane(arg).show/hide and it'll log it as a function, so why is it when I call Pane(arg).show it doesn't do anything? The functions in the object work (outside of the constructor function in their own functions).
The function is returning the state object, so it will never return the constructed object, even when used with new. Since state contains those methods, you can just call the function and immediately invoke one of the methods on the returned object.
Now, if you're expecting show and hide to automatically have access to data via closure, it's not working because you're shadowing the variable by declaring the method parameters. You can do this instead:
function Pane(data) {
var state = {
show: function() {
var data = data || arguments[0];
var pane = document.querySelector('.pane[data-content='+data.target+']');
pane.classList.add('active');
},
hide: function() {
var data = data || arguments[0];
var pane = document.querySelector('.pane[data-content='+data.target+']');
var paneSibling = $(pane.parentNode.childNodes);
paneSibling.each(function(sibling) {
if(check.isElement(sibling)) {
var isActive = sibling.classList.contains('active');
if(sibling != pane && isActive) {
sibling.classList.remove('active');
};
};
});
}
}
return state;
}
Then you can use it like this:
Pane({}).show();
Or like this:
var p = Pane();
p.show();
Or force a new argument when needed:
p.show({foo:'bar'});
You are overriding the original argument in each function.
So what you are doing is to find elements with the attribute data-content='undefined'
This obviously doesn't work.
So to fix this you should just remove the data argument in the show/hide function.
Here is a plnkr showing the problem and fix.

JavaScript error when creating custom object

I am finding that when I call record.create() then sometimes it succeeds, and at other times it throws an error saying that no such method exists, even though record object has its properties set appropriately.
Am I using create method incorrectly? May be I am missing something about JavaScript custom object syntax.
<script language="javascript" type="text/javascript">
var record = {
RecordID : null,
CustomerID : null,
CompanyID : null,
create : function() {
var obj = new Object();
obj.RecordID = "";
obj.CustomerID = "";
return obj;
}
};
function pageLoad(sender, eventArgs) {
{
//*******SUCCEEDS********
record = record.create()
}
function RadGrid1_RowSelected(sender, args) {
currentRowIndex = args.get_gridDataItem().get_element().rowIndex;
var dataItem = args.get_gridDataItem().get_dataItem();
recordId = dataItem["Record_ID"];
if (tableView.get_selectedItems().length == 1) {
record = record.create();
record.RecordID = dataItem["Record_ID"];
record.CustomerID = dataItem["Customer_ID"];
setValues();
}
else if (tableView.get_selectedItems().length > 1) {
record= record.create();//****FAILS ALWAYS even when record object has non-null properties*******
}
if ($.inArray(recordId, recordIds) == -1) {
recordIds.push(recordId);
}
}
</script>
UPDATE : This is what worked for me.
Instead of using the create method on 'record' global object, I ended up using a simple approach. Just call a custom method 'resetRecord' everytime I wanted to call the create( ) method on record object. That way I have no errors and my logic works perfectly.
function resetRecord() {
record.RecordID = "";
record.CustomerID = "";
record.CompanyID = "";
}
It won't work after the first call because you are overwriting the record object. This will destroy any create() method as the object returned does not have this method/property.
For you update, variables have function level scope. You are using the global record inside of RadGrid1_RowSelected.
I'm not entirely sure what you are doing but this will get you past your first problem.
function RadGrid1_RowSelected(sender, args) {
var newRecord;
currentRowIndex = args.get_gridDataItem().get_element().rowIndex;
var dataItem = args.get_gridDataItem().get_dataItem();
recordId = dataItem["Record_ID"];
if (tableView.get_selectedItems().length == 1) {
record = record.create();
record.RecordID = dataItem["Record_ID"];
record.CustomerID = dataItem["Customer_ID"];
setValues();
}
else if (tableView.get_selectedItems().length > 1) {
newRecord= record.create();//****FAILS ALWAYS even when record object has non-null properties*******
}
if ($.inArray(recordId, recordIds) == -1) {
recordIds.push(recordId);
}
}

javascript jquery function is this somehow wrong?

function rebuildJSONObject(){
$.getJSON('services.json', function(data) {
//stof start
var input = data;
var output = { myservices: [] };
for (var key in input) {
if (input.hasOwnProperty(key)) {
for (var i = 0, hostsinfo = input[key].hostsinfo; i < hostsinfo.length; i++) {
output.myservices.push({
'nametag': key,
'hostidn': hostsinfo[i]['hostidn'],
'details': hostsinfo[i]['details'],
'currstatus': hostsinfo[i]['currstatus'],
'currstatusclass': hostsinfo[i]['currstatusclass']
});
}
}
}
//stof end
return output;
});
}
//setting it for use later in the script
var serviceJSONObject = rebuildJSONObject();
I know the stuff going on in the function is working properly cause if I apply it to a click event it works charming. However I would rather load the JSON object into memory once and work with it client side there after unless saved. My Problem is however anywhere I call "serviceJSONObject" I get an "undefined" error.
So How am I doing this wrong and how would I define a variable like this early in the game so the rest of the script can use said variable.
The issue is that output is returned before the callback function is called. You should be able to save the value to serviceJSONObject by using a closure:
function rebuildJSONObject(serviceJSONObject){
$.getJSON('services.json', function(data) {
//stof start
var input = data;
// Use the serviceJSONObject that is passed into rebuildJSONObject
serviceJSONObject = { myservices: [] };
for (var key in input) {
if (input.hasOwnProperty(key)) {
for (var i = 0, hostsinfo = input[key].hostsinfo; i < hostsinfo.length; i++) {
serviceJSONObject.myservices.push({
'nametag': key,
'hostidn': hostsinfo[i]['hostidn'],
'details': hostsinfo[i]['details'],
'currstatus': hostsinfo[i]['currstatus'],
'currstatusclass': hostsinfo[i]['currstatusclass']
});
}
}
}
//stof end
});
}
//setting it for use later in the script
var serviceJSONObject;
rebuildJSONObject(serviceJSONObject);
Why not add a cache property to a function that will store the result of the initial output (loaded via ajax) and returning the saved state to any consecutive call.
function rebuildJSONObject(callback) {
var self = this;
if (typeof self.cache !== 'undefined') {
if (typeof callback === 'function') {
callback(self.cache);
}
return;
}
$.getJSON('services.json', function(data) {
//stof start
var input = data,
output = { myservices: [] };
for (var key in input) {
if (input.hasOwnProperty(key)) {
for (var i = 0, hostsinfo = input[key].hostsinfo; i < hostsinfo.length; i++) {
output.myservices.push({
'nametag': key,
'hostidn': hostsinfo[i]['hostidn'],
'details': hostsinfo[i]['details'],
'currstatus': hostsinfo[i]['currstatus'],
'currstatusclass': hostsinfo[i]['currstatusclass']
});
}
}
}
//stof end
self.cache = output;
if (typeof callback === 'function') {
callback(self.cache);
}
return;
});
}
EDIT: For the first time you will need to call this function asynchronously and supply a callback function, for example
rebuildJSONObject(function(output) {
/*
* Process your output here
*/
console.log(output);
});
Each consecutive time you can again use it synchronously:
console.log(rebuildJSONObject.cache);
There are a couple of problems with this.
The call to getJSON is asynchronous so you need to be careful you don't try to use the results before the call has returned your results.
The way it is at the moment, the results will not be returned to serviceJSONObject. The return output statement is setting the return for the anonymous function, not the return value for rebuildJSONObject, so the results will just disappear. If you want the results to be available elsewhwere in code you will either need to store them in a global variable or access them inside the callback.

Categories

Resources