Hello,
I’ve had some issues with async functions in the past, and have had to get help on the forum, and in the end, I was instructed on how to use a Promise with API data that was being pushed into an array. Now, however, I’m working on a personal project that requires multiple API calls that push data into JSON objects, and so the things I had tried before that used to work for arrays, don’t work as nicely with JSON objects. What is the best approach to doing this? This app uses express, so basically my overarching problem is that I’m performing the res.json
function before the JSON object is filled out with the data it needs.
Can you provide some example content to understand the scenario?
@bunnyvishal6
Sheet.getCells
is a function within a Google Sheets API FYI, but it’s basically just a normal API call.
var rowersOptions = {
'min-row': 4,
'max-row': maxRows, //Defined earlier
'min-col': 2,
'max-col': 2,
'return-empty': true
};
sheet.getCells(rowersOptions, function(err, cells) {
var CellData = {};
//Get Rowers
var rowers = [];
for (var i = 0; i<cells.length; i++) {
rowers.push(cells[i].value);
}
});
var date = "6/18" //NEED TO CHANGE DATE TO REAL DATE
//Function for finding data of Women's Sculls
function getWomen (col) {
var columnOptions = {
'min-row': 4,
'max-row': maxRows,
'min-col': col,
'max-col': col,
'return-empty': true
};
sheet.getCells(columnOptions, function(err, cells) {
for (var i = 0; i<cells.length; i++) {
var name = rowers[i];
if (cells[i].value === "1") {
finalComingWomen[name] = "YES";
} else if (cells[i].value === "0") {
finalComingWomen[name] = "NO";
} else {
finalComingWomen[name] = "N/A";
}
}
});
}
//Finding Data for Open Sculls
function getOpen (col) {
var columnOptions = {
'min-row': 4,
'max-row': maxRows,
'min-col': col,
'max-col': col,
'return-empty': true
};
sheet.getCells(columnOptions, function(err, cells) {
for (var i = 0; i<cells.length; i++) {
var name = rowers[i];
if (cells[i].value === "1") {
finalComingOpen[name] = "YES";
} else if (cells[i].value === "0") {
finalComingOpen[name] = "NO";
} else {
finalComingOpen[name] = "N/A";
}
}
});
}
//Finding Column Applicable for each data set, and then grabbing data from Google Sheets API with the column number
var dateOptions = {
'min-row': 2,
'max-row': 2,
'return-empty': true
};
sheet.getCells(dateOptions, function(err, cells) {
for (var i = 0; i<cells.length; i++) {
if (date == cells[i].value){
getWomen(Number(cells[i].col));
getOpen(Number(cells[i].col) + 1);
break;
}
}
});
res.json({finalComingOpen, finalComingWomen]});
@njanne19 as functions invlove some async operation. You should use promises or you can use traditional callbacks.
Note that you are using for loops with async data. Then before completion of the async calls for loop ends and res.json will get called before the finalComingWomen and finalComingOpen get filled with required data.
I tried with callbacks if you like you can see this. And where did you declare “finalComingWomen” and “finalComingOpen” in your code? I assume that these were defined previously or these are global variables.
var rowersOptions = {
'min-row': 4,
'max-row': maxRows, //Defined earlier
'min-col': 2,
'max-col': 2,
'return-empty': true
};
sheet.getCells(rowersOptions, function(err, cells) {
var CellData = {};
//Get Rowers
var rowers = [];
for (var i = 0; i < cells.length; i++) {
rowers.push(cells[i].value);
//the ieteration came to an end
if (i == cells.length - 1) {
var date = "6/18" //NEED TO CHANGE DATE TO REAL DATE
//Function for finding data of Women's Sculls
function getWomen(col, cb) {
var columnOptions = {
'min-row': 4,
'max-row': maxRows,
'min-col': col,
'max-col': col,
'return-empty': true
};
sheet.getCells(columnOptions, function(err, cells) {
for (var i = 0; i < cells.length; i++) {
var name = rowers[i];
if (cells[i].value === "1") {
finalComingWomen[name] = "YES";
} else if (cells[i].value === "0") {
finalComingWomen[name] = "NO";
} else {
finalComingWomen[name] = "N/A";
}
//During the iteration when i == cells.length - 1 i is the maximum index in cells array.
//Call the callback so that this function is done and got the required data
if (i == cells.length - 1) {
//call the next one
cb();
}
}
});
}
//Finding Data for Open Sculls
function getOpen(col, cb) {
var columnOptions = {
'min-row': 4,
'max-row': maxRows,
'min-col': col,
'max-col': col,
'return-empty': true
};
sheet.getCells(columnOptions, function(err, cells) {
for (var i = 0; i < cells.length; i++) {
var name = rowers[i];
if (cells[i].value === "1") {
finalComingOpen[name] = "YES";
} else if (cells[i].value === "0") {
finalComingOpen[name] = "NO";
} else {
finalComingOpen[name] = "N/A";
}
//During the iteration when i == cells.length - 1 i is the maximum index in cells array.
//Call the callback so that this function is done and got the required data
if (i == cells.length - 1) {
cb();
}
}
});
}
//Finding Column Applicable for each data set, and then grabbing data from Google Sheets API with the column number
var dateOptions = {
'min-row': 2,
'max-row': 2,
'return-empty': true
};
sheet.getCells(dateOptions, function(err, cells) {
var cellsCount = 0;
function getData() {
if (date == cells[cellsCount].value) { //if the date is cells[cellsCount].value then we get required data
//call to getWomen
getWomen(Number(cells[cellsCount].col), function() {
//call to getOpen
getOpen((Number(cells[cellsCount].col) + 1), function() {
res.json({ finalComingOpen, finalComingWomen });
});
});
} else { //else means date not equals to cells[cellsCount].value increase the cellsCount by one as if in for loop
cellsCount++;
if (cellsCount < cells.length) { //if the new cellsCount is less than cells.length then call this function again.
getData();
}
}
}
});
}
}
});
@bunnyvishal6
I tried doing something like this, but now it tells me that my variable rowers
is not defined. However, it seems to be in the scope of the function that it comes up as undefined in.
var rowersOptions = {
'min-row': 4,
'max-row': maxRows, //Defined earlier
'min-col': 2,
'max-col': 2,
'return-empty': true
};
sheet.getCells(rowersOptions, function(err, cells) {
var CellData = {};
//Get Rowers
var rowers = [];
for (var i = 0; i<cells.length; i++) {
rowers.push(cells[i].value);
}
});
var date = "6/18" //NEED TO CHANGE DATE TO REAL DATE
function getMyAsync (col) {
return new Promise(function(resolve, reject) {
var ticker = 0;
var columnOptions1 = {
'min-row': 4,
'max-row': maxRows,
'min-col': col,
'max-col': col,
'return-empty': true
};
var columnOptions2 = {
'min-row': 4,
'max-row': maxRows,
'min-col': col+1,
'max-col': col+1,
'return-empty': true
};
sheet.getCells(columnOptions1, function(err, cells) {
for (var i = 0; i<cells.length; i++) {
var name = rowers[i];
if (cells[i].value === "1") {
finalComingWomen[name] = "YES";
} else if (cells[i].value === "0") {
finalComingWomen[name] = "NO";
} else {
finalComingWomen[name] = "N/A";
}
if (i == cells.length - 1) {
ticker ++;
}
}
});
sheet.getCells(columnOptions2, function(err, cells) {
for (var i = 0; i<cells.length; i++) {
var name = rowers[i];
if (cells[i].value === "1") {
finalComingOpen[name] = "YES";
} else if (cells[i].value === "0") {
finalComingOpen[name] = "NO";
} else {
finalComingOpen[name] = "N/A";
}
if (i == cells.length - 1) {
ticker ++;
}
}
});
if (ticker == 2) {
resolve();
}
});
}
//Finding Column Applicable for each data set, and then grabbing data from Google Sheets API with the column number
var dateOptions = {
'min-row': 2,
'max-row': 2,
'return-empty': true
};
sheet.getCells(dateOptions, function(err, cells) {
for (var i = 0; i<cells.length; i++) {
if (date == cells[i].value){
getMyAsync(Number(cells[i].col)).then(function() {
res.json({finalComingOpen, finalComingWomen});
});
break;
}
}
});
@njanne19 no rowers is not in scope of the functions that are using the rowers variable. Define all your async functions inside the function which declares rowers.
var rowersOptions = {
'min-row': 4,
'max-row': maxRows, //Defined earlier
'min-col': 2,
'max-col': 2,
'return-empty': true
};
sheet.getCells(rowersOptions, function(err, cells) {
var CellData = {};
//Get Rowers
var rowers = [];
for (var i = 0; i < cells.length; i++) {
rowers.push(cells[i].value);
//when iteration comes to an end
if (i == cells.length - 1) {
//define your async function here
function getMyAsync(col) {
return new Promise(function(resolve, reject) {
var ticker = 0;
var columnOptions1 = {
'min-row': 4,
'max-row': maxRows,
'min-col': col,
'max-col': col,
'return-empty': true
};
var columnOptions2 = {
'min-row': 4,
'max-row': maxRows,
'min-col': col + 1,
'max-col': col + 1,
'return-empty': true
};
sheet.getCells(columnOptions1, function(err, cells) {
for (var i = 0; i < cells.length; i++) {
var name = rowers[i];
if (cells[i].value === "1") {
finalComingWomen[name] = "YES";
} else if (cells[i].value === "0") {
finalComingWomen[name] = "NO";
} else {
finalComingWomen[name] = "N/A";
}
if (i == cells.length - 1) {
ticker++;
}
}
});
sheet.getCells(columnOptions2, function(err, cells) {
for (var i = 0; i < cells.length; i++) {
var name = rowers[i];
if (cells[i].value === "1") {
finalComingOpen[name] = "YES";
} else if (cells[i].value === "0") {
finalComingOpen[name] = "NO";
} else {
finalComingOpen[name] = "N/A";
}
if (i == cells.length - 1) {
ticker++;
}
}
});
if (ticker == 2) {
resolve();
}
});
}
var date = "6/18" //NEED TO CHANGE DATE TO REAL DATE
//Finding Column Applicable for each data set, and then grabbing data from Google Sheets API with the column number
var dateOptions = {
'min-row': 2,
'max-row': 2,
'return-empty': true
};
sheet.getCells(dateOptions, function(err, cells) {
for (var i = 0; i < cells.length; i++) {
if (date == cells[i].value) {
getMyAsync(Number(cells[i].col)).then(function() {
res.json({ finalComingOpen, finalComingWomen });
});
break;
}
}
});
}
}
});
@bunnyvishal6 @marzelin
I was able to work it out on my own, and it seems like everything is in order. The functions work in order, and I’m satisfied with that portion. My only problem now is that I have four variables,
womenComing womenNotComing openComing openNotComing
that all end up as blank arrays after the function runs, even though I explicitly state, if the function finds a match of a 1, array.push
the corresponding rower’s name into the array womenComing
. This is a small example because it goes beyond that, but see down below, it’s such a weird bug.
Note that all of the variables that you do not see declared were declared earlier in the program. The arrays that are not currently working were all declared in the same manner: var arrayX = [];
var rowersOptions = {
'min-row': 4,
'max-row': maxRows, //Defined earlier
'min-col': 2,
'max-col': 2,
'return-empty': true
};
var rowers = [];
//Get Rowers
sheet.getCells(rowersOptions, function(err, cells) {
var CellData = {};
for (var i = 0; i<cells.length; i++) {
rowers.push(cells[i].value.toString());
}
});
var date = "6/18" //NEED TO CHANGE DATE TO REAL DATE
function getWomen (col) {
var columnOptions1 = {
'min-row': 4,
'max-row': maxRows,
'min-col': col,
'max-col': col,
'return-empty': true
};
return new Promise(function(resolve, reject) {
sheet.getCells(columnOptions1, function(err, cells) {
for (var i = 0; i<cells.length; i++) {
if (cells[i].value === "1") {
womenComing.push(rowers[i]);
finalComingWomen[rowers[i]] = "YES"; //JSON Object defined earlier
} else if (cells[i].value === "0") {
womenNotComing.push(rowers[i]);
finalComingWomen[rowers[i]] = "NO";
} else {
finalComingWomen[rowers[i]] = "N/A";
}
if (i == cells.length - 1 ){
console.log("This should come first");
resolve();
}
}
});
});
}
function getOpen (col) {
var columnOptions2 = {
'min-row': 4,
'max-row': maxRows,
'min-col': col+1,
'max-col': col+1,
'return-empty': true
};
return new Promise(function(resolve, reject) {
sheet.getCells(columnOptions2, function(err, cells) {
for (var i = 0; i<cells.length; i++) {
if (cells[i].value === "1") {
openComing.push(rowers[i]);
finalComingOpen[rowers[i]] = "YES"; //JSON Object defined earlier
} else if (cells[i].value === "0") {
openNotComing.push(rowers[i]);
finalComingOpen[rowers[i]] = "NO";
} else {
finalComingOpen[rowers[i]] = "N/A";
}
if (i == cells.length - 1 ){
console.log("This should come second");
resolve();
}
}
});
});
}
//Finding Column Applicable for each data set, and then grabbing data from Google Sheets API with the column number
var dateOptions = {
'min-row': 2,
'max-row': 2,
'return-empty': true
};
sheet.getCells(dateOptions, function(err, cells) {
for (var i = 0; i<cells.length; i++) {
if (date == cells[i].value){
Promise.all([getWomen(Number(cells[i].col)), getOpen(Number(cells[i].col))]).then(() => {
console.log("this should come third");
res.json({finalComingOpen, finalComingWomen});
}).then(emailSends());
break;
}
}
});