Javascript return function in another function - javascript

I have a javascript which is like this
function one (var1, var2){
var var3= var1+var2;
return var3;
}
function two( var4, var5){
var var6=var4*var5;
return var6;
}
function three(var7, var8){
var9=var7/var8;
return var9;
}
var first = one(2, 4);
var second= two(first, 8);
var third= three(second, 9);
I want all the function to be separate because they each are like module which would handle different operations. So I do not want to use callback, I have tried
$.ajax(first = one(2,4))
.then({second=two(first, 8)})
.then(three(second,9))
I have also tried this
$.ajax()
.then(function(first=one(2,4){
return first;
})
.then(function(second=two(first,4){
return second;
})
I have also tried this
$.ajax({
first:one(2,4),
second:two(first,4),
third:three(second,9),
})
.then(function(first=one(2,4){
return first;
})
.then(function(second=two(first,4){
return second;
})
this may sound funny but I even tried
var third= three(two(one(2, 4), 8), 9);
amongst many others.
All of them show operation takes place with the first function and other functions but the it does not give me result from previous function
This is an update to the above.
Modification
I do not want to use promise in the other functions as some other functions would also call those functions and they would not be expecting a promise but a valid data
function modifyData(details){
for(var x=0 ;x<array.length;x++){
//this would do a massive loop which would
//return a json string that would be
}
}
function tableFunction(url, tableNameVar){
//json fields
var details=[];
details[0] = 'name';
details[1] = 'sex';
details[2] = 'eye_color';
details[3] = 'height';
details[4] = 'body_built';
var jsonData='';
var main = "";
$(document).ready(function(){
$('#'+tableNameVar+'').dataTable({
destroy: true,
data: JSON.parse(extraFunctionProcess(modifyData(details),details)),
columns:[
{title: "Name", data:"name"} ,
{title: "Gender", data:"sex"} ,
{title: "Eye color", data:"eye_color"} ,
{title: "Height", data:"height"} ,
{title: "Body built", data:"body_built"}
]
});
});
}
I want to process the data and put it inside the table. The extraFunctionProcess has worked if the data is passed
straight into the data field without putting it inside the modifyData function.
which is instead of the above it is
data: JSON.parse(extraFunctionProcess(fullData,details))
This has worked but due to the modification which I have done, it has brought up an error in my browser console which is
undefined inside the extraFunctionProcess.
I just shortened the code into I put online now.

I have actually found a solution to the problem. The modifyData function was the one with the problem. The return was inside another function.
Intead of the following
function modifyData(details){
for(var x=0 ;x<array.length;x++){
//this would do a massive loop which would
//return a json string that would be inside a function
}
}
function modifyData(details){
for(var x=0 ;x<array.length;x++){
return functionName(callback to be done);
//this would do a massive loop which would
//return a json string that would be
}
}

Related

Google Apps Script web app. Use variable outside of an if forEach statement

I'm new to Javascript, I thought I was going ok but I can't figure out this problem.
I'm using Google Apps script to get data from my Google Sheets doc and if a name in column A matches "Sundries" then show the price in Column B.
My script works when I use alert inside the if forEach function but when I move alert outside of it, it breaks. I throws up alerts saying undefined, undefined, undefined, the correct price then undefined, undefined again.
I'm guessing it's something to do with forEach but I don't know away around it.
Here's the section of script that is my problem.
document.addEventListener("DOMContentLoaded", afterSidebarLoads);
//get the data from Google Sheets
function getRates() {
const sheet = SpreadsheetApp.openById("fwffwfwefewdwedwedwedwedwedwedwed").getSheetByName("tab name");
return sheet.getRange(15, 1, sheet.getLastRow()-14, 2).getValues();
}
// runs the script
function afterSidebarLoads() { // Function Part: 1
google.script.run.withSuccessHandler(getSundriesyRate).getRates();
}
// here's my problem
function getSundriesyRate(arrayOfArrays){ // Function Part: 2
var sundriesRate = document.getElementById("sundries-rate");
arrayOfArrays.forEach(function(r){ // r= one of the lines in the aray
var div = document.createElement("div");
if (r[0] === "Sundries") { // this does match
var dhello = r[1].toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2});
alert(dhello); // works
} else {
}
alert(dhello); // doesn't work
});
}
Thanks
By create a variable outside the forEach loop and pass the value into the variable. then you will be able to use this variable outside the loop.
If you are expecting to return multiple values, you should use a array or dictionaries to store the data.
document.addEventListener("DOMContentLoaded", afterSidebarLoads);
//get the data from Google Sheets
function getRates() {
const sheet = SpreadsheetApp.openById("fwffwfwefewdwedwedwedwedwedwedwed").getSheetByName("tab name");
return sheet.getRange(15, 1, sheet.getLastRow()-14, 2).getValues();
}
// runs the script
function afterSidebarLoads() { // Function Part: 1
google.script.run.withSuccessHandler(getSundriesyRate).getRates();
}
// here's my problem
function getSundriesyRate(arrayOfArrays){ // Function Part: 2
var sundriesRate = document.getElementById("sundries-rate");
var dhello;
arrayOfArrays.forEach(function(r){ // r= one of the lines in the aray
var div = document.createElement("div");
if (r[0] === "Sundries") { // this does match
dhello = r[1].toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2});
alert(dhello); // works
} else {
}
//alert(dhello); // doesn't work (it's return undefined because in this forEach loop, it will go through every line of the array and it does not find the match , it returns nothing.)
});
alert(dhello); // you can access this variable here.
}

Javascript function always returns 0

I am writing a function which searches for a value in my IndexedDB and if it finds one, then it should return 1, else it should return 0. The problem is that it always returns 0 though the value exists in a database (variable arr is incremented, but 0 is returned as a result). The code is as follows:
searchAllValues: function(store, type)
{
var arr = 0;
AAA.initDb(function()
{
var obj = {};
AAA.aaaDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
if(storeresult.value.value == type ){
arr++;
}else{console.log('value NOT found');}
storeresult ? (obj[storeresult.key] = storeresult.value.value, storeresult["continue"]()) : callback(obj)
}
});if(arr!=0){return 1}else{return 0}
}
EDIT_1:
Ok, I have refactored the code as follows:
addInfo: function(store, type, info)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
console.log('value of storeresult==>'+storeresult.value.value);
if(storeresult.value.value == info)
{
arr.push(storeresult.value.values);return;//If it finds something it should stop here, no more search or anything to be done
}else
{
console.log('continuing..');
storeresult['continue']();
}
console.log('arr length==> '+arr.length);//If it finds nothing after the looping the whole DB, I want it to print this statement, only once (to send it to my DB actually but sending code is omitted for simplicity).
}
}
Instead I get console.log('arr length==>') statement executed 2 times, for every key in my object store (there are 2 of them actually). So it is doing the code when it finds nothing AND when it finds the value in the DB. Any ideas how to fix it?
Any ideas would be welcome, Thank You
Because by the time the line if(arr!=0){return 1}else{return 0} is executed the db transaction is not complete and value of arr is 0. Though never used indexedDb, but webSql do take some extra miliseconds to read from DB.
Try to put your return logic inside the onsuccess function where you incrementing the arr. You can simply test it by printing value of arr just before your return logic
You need to learn about how to write asynchronous javascript. There are several other indexedDB questions where there are explanations as to why this happens.
For example: Uncaught TypeError: Cannot read property 'transaction' of null with an indexeddb
function addInfo(store, type, info, next)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
console.log('value of storeresult==>'+storeresult.value.value);
if(storeresult.value.value == info)
{
arr.push(storeresult.value.values);
next(arr);//If it finds something it should stop here, no more search or anything to be done
}else
{
console.log('continuing..');
storeresult.continue();
}
console.log('arr length==> '+arr.length);//If it finds nothing after the looping the whole DB, I want it to print this statement, only once (to send it to my DB actually but sending code is omitted for simplicity).
}
}
Added an extra parameter called 'next' to your the addInfo function.
'next' param is the very last function called if the condition (storeresult.value.value == info) is true.
The next function which you create, will use the 'arr' variable and do whatever with it
your 'return statement' doesnt work the sameway with asynchronous functions, would highly advice you search up asynchronous functions to get a gist of how its different to regular functions
This is how you would call your newly edited function:
addInfo(store,type,info,function(arr){
//do something with arr
})
Note that you have a potential state which would break your code
what if the cursor reaches the end of its iterations and never meets that condition (storeresult.value.value == info). storeresult would be null, and the check for the condition (null.value.value == info) will throw an exception
correction:
function addInfo(store, type, info, next)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store){
var storeresult = store.target.result;
if(storeresult){
if(storeresult.value.value == info){
arr.push(storeresult.value.values);
next(arr);
}else storeresult.continue();
}else next();
}
}
And when you call it you handle the scenario whereby arr == null
addInfo(store,type,info,function(arr){
if(arr){
//do something with arr
}else{
//do somethingelse when arr == null
}
})

Put data from a IndexedDB data base in a variable

I'm trying to put the data read from the database in a variable. I have tryed many things, including a callback function, but nothing looks to work when the process is outside of the "opencursor().onsuccess" function scope.
The "Alert 1" show the result correctly, but "Alert 2" and "Alert 3" don't.
I'm calling the 'main()' function from HTML code.
I'm really frustrated, because I have been mining internet searching for the solution without any positive result.
Can anybody help me, please?
Thanks a lot.
var data=[];
function kkeyget(t1, db_name, db_version)
{
var request = indexedDB.open(db_name, db_version);
request.onerror=function()
{
alert("Error");
}
request.onsuccess=function(event)
{
var db=this.result;
var trans = db.transaction(t1, "readonly");
var objectStore = trans.objectStore(t1);
objectStore.openCursor().onsuccess = function(event)
{
var cursor = event.target.result;
if (cursor)
{
data.push(cursor.value);
//Alert 1:
alert(data[0].id);
cursor.continue();
}
else alert("No more entries!");
};
}
//Alert 2:
alert(data[0].id);
}
function main()
{
kkeyget("agenda", "example_db", 1);
//Alert 3:
alert(data[0].id);
}
Correct. Because all indexedDB actions are asynchronous, your code will run:
alert 2 // undefined
alert 3 // undefined
alert 1 // correct
In order to get this closer to a synchronous action, you need to have it call a new function after it's done collecting data. Where your alert("No more entries!") is.
Instead of trying to return a key, pass in a custom callback function that takes the retrieved key as its argument.
// Your old function slightly modified
function kkeyget(t1, db_name, db_version, callback, fallback) {
// ... yada yada yada
objectStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if(cursor) {
callback(cursor.value);
} else {
fallback();
}
}
}
// Now in your calling code:
kkeyget('a','b',1, function(id) {
// Do something with the 'id'
// here in this anonymous function callback
}, function() {
// Do something here to indicate no match
});

jQuery deferred not working for me?

I'm trying to use the jQuery when function, in order to wait until an Ajax request completes before proceeding onwards, but am clearly getting something wrong.
My console output looks like this:
geocodeMaster
geocode Canary Wharf
Object
geocode
Object
address is blank, returning 51.501885 -0.190894
proceeding
Uncaught TypeError: Cannot read property '0' of undefined
Object
Object
The final two Objects are the output from the second call to geocode. Why does the code show proceeding before the output of the second call?
My code looks like this:
function geocode(address, geodata) {
console.log('geocode', address, geodata);
geodata['street'] = address;
if (address=="") {
console.log('address is blank, returning ' + current_latlng[0], current_latlng[1]);
return [current_latlng[0], current_latlng[1]];
}
$.ajax({
url: CS_API + 'geocoder.json',
data: geodata,
dataType: 'jsonp',
jsonpCallback: 'places',
success: function(from_data) {
console.log(from_data);
if (from_data.results.result!=undefined){
var from_result = from_data.results.result;
console.log(from_result)
return [from_result.latitude, from_result.longitude];
} else {
return false;
}
},
error: function(data) {
return false;
}
});
}
function geocodeMaster(place_from,place_to) {
console.log('geocodeMaster');
geodata['key'] = CS_API_KEY;
if (current_latlng!=null) {
geodata['n'] = current_latlng[0] + 0.1;
geodata['e'] = current_latlng[1] + 0.1;
geodata['s'] = current_latlng[0] - 0.1;
geodata['w'] = current_latlng[1] - 0.1;
}
var start_coords,finish_coords;
$.when(start_coords=geocode(place_from,geodata),finish_coords=geocode(place_to,geodata)).then(function(){
console.log('proceeding');
console.log(start_coords[0],start_coords[1],finish_coords[0],finish_coords[1]);
});
}
Is the problem that the objects supplied to when() are not Deferred objects? If so, how can I make them into Deferred objects, while keeping the information that I need to collect - start_lat, etc?
You must return a deferred object from the geocode function. Try :
return $.ajax(..
You cannot store the return value directly into values (it does not work the way it's written now). You have to store them somewhere else, so that the line that calls the when simply reads :
$.when(geocode(place_from,geodata),geocode(....
To solve this, you could pass to geocode an empty object, and have that function save its result in it, for example :
var start_coords = {};
var finish_coords = {};
$.when(geocode(place_from,geodata,start_coords),geocode(place_to,geodata,finish_coords) ...

Multidimensional Arrays and jQuery's getJSON

I am submitted a getJSON request to a controller in my application, this controller is returning valid JSON with 2 "applications." I know this for a fact as if I move the alert statement to within jQuery's each function it will give me the expected result.
I am attempting to store this data within a multidimensional array to later be used with extJS' Menu Control.
Code:
Ext.onReady(function() {
var applicationList = [];
jQuery.getJSON('index.php/applications', function(data) {
jQuery.each(data.applications, function (i, app) {
applicationList[i] = [];
applicationList[i]['text'] = app['title'];
applicationList[i]['id'] = app['slug'];
});
});
alert(applicationList[0]['text']);
var applicationMenu = Ext.menu.Menu({
items: applicationList
});
});
JSON Response:
{"applications":[{"slug":"test","title":"Test"},{"slug":"hardware","title":"Hardware"}]}
Expected Result:
Test
Actual Result (from Firebug):
applicationList[0] is undefined
If I replace the alert() above, with the following code I get one alert window with the text "remove":
for (p in applicationList) {
alert(p);
}
Now, my thinking is that the JSON request isn't completing in-time for the alert() so I'll use a named callback function to ensure the request has completed:
var data;
jQuery.getJSON('index.php/applications', get_applications(data));
function get_applications(data) {
jQuery.each(data.applications, function (i, app) {
applicationList[i] = [];
applicationList[i]['text'] = app['title'];
applicationList[i]['id'] = app['slug'];
});
};
But now Firebug is telling me that data is undefined...
I feel like I am almost there, but I've been almost there for the past hour and I feel as if I am just polluting the source now in trying to get it to work.
This should do it:
Ext.onReady(function() {
var applicationList = [];
var applicationMenu;
jQuery.getJSON('index.php/applications', function(data) {
jQuery.each(data.applications, function (i, app) {
applicationList[i] = [];
applicationList[i]['text'] = app['title'];
applicationList[i]['id'] = app['slug'];
});
applicationMenu = Ext.menu.Menu({
items: applicationList
});
});
});
Your thinking is right; the reason it is not working is because AJAX is an asynchronous process and as you fire off the getJSON function javascript keeps on trucking along. Your solution doesn't work because making it a named callback is not changing the fact that it won't be fired until you've already tried to initialize the Menu. All my solution is doing is moving the Menu initilization code INSIDE the callback, as it is then and only then that you will have access to the filled out applicationList.
You're right, you should use your "applicationList" variable only after the getJSON callback has finished.
You should call Ext.menu.Menu() inside your getJSON callback, after jQuery.each().
Paolo Bergantino's solution should work, but you can also do it your way, using a named callback function -- you just made some small errors in your code:
data should not be declared as a variable -- data in "function get_applications(data)" just stands for whatever .getJSON returns
The callback function in .getJSON should just be the name of the function, without (data)
Here's the corrected code:
jQuery.getJSON('index.php/applications', get_applications);
function get_applications(data) {
jQuery.each(data.applications, function (i, app) {
applicationList[i] = [];
applicationList[i]['text'] = app['title'];
applicationList[i]['id'] = app['slug'];
});
};
$.getJSON("getq2.php", {
yr: year,
typ: type
}, function(data) {
var items1 = new Array();
var j = 0;
for (var i in data) {
var items = new Array();
items.push(data[i][0], Number(data[i][1]));
items1[j++] = items;
}
console.log(items1);
var plot1 = jQuery.jqplot('chartContainer', [items1], {
seriesDefaults: {
// Make this a pie chart.
renderer: jQuery.jqplot.PieRenderer,
rendererOptions: {
startAngle: 180,
sliceMargin: 2,
dataLabelThreshold: 2,
// Put data labels on the pie slices.
// By default, labels show the percentage of the slice.
showDataLabels: true,
}
},
grid: {
borderWidth: 0,
shadow: false,
background: '#d8d6cb'
},
legend: {
placement: 'outside',
show: true,
location: 'e',
background: 'transparent',
marginRight: '30px'
}
});
});

Categories

Resources