I'm building a website using Airtable API to scrape data from an Airtable spreadsheet using JS.
I'm running into a fairly simple(?) problem using JavaScript.
I'm putting data from the spreadsheet into a string array names. console.log(names[0]) prints out the string value correctly, but when I try to do something like:
var test = names[0];
console.log(test),
It prints out undefined
Why does this happen?
My Code:
var names = [];
var locations = [];
//ACCESS AIRTABLE API (GET DATA FROM AIRTABLE SPREADSHEET)
var Airtable = require('airtable');
var base = new Airtable({apiKey: 'keyQ7YUX3SUECVL4C'}).base('appSmUKDnFdEAT1YF');
base('Members').select({
view: "Grid view"
}).eachPage(function page(records, fetchNextPage) {
//Fill arrays with data from spreadsheet
records.forEach(function(record) {
names.push(record.get('parsedName'));
locations.push(record.get('parsedLocation'));
});
fetchNextPage();
}, function done(err) {
if (err) { console.error(err); return; }
});
Related
I have read elsewhere (Reading PDF file using javascript) how to read the texts in a pdf file, and showing them in the console. This is done using the following code:
var PdfReader = require("pdfreader").PdfReader;
new PdfReader().parseFileItems("sample.pdf", function(err, item){
if (item && item.text)
console.log(item.text);
});
My question is, instead of showing the texts in the console using console.log, how do I store them in an array, for use at a later stage of the script?
Initialize an array above the parse function, then push the items to the array:
var PdfReader = require("pdfreader").PdfReader;
var arr = [];
new PdfReader().parseFileItems("sample.pdf", function(err, item){
if (item && item.text){
arr.push(item.text);
}
});
console.log(arr);
const { PdfReader } = require("pdfreader");
var arr = [];
new PdfReader().parseFileItems("test/sample.pdf", (err, item) => {
if (err) console.error("error:", err);
else if (!item) console.log(arr);
else if (item.text) arr.push(item.text);
});
I modified code from official example: https://github.com/adrienjoly/npm-pdfreader#raw-pdf-reading
My Firebase data base contains JSON objects, each with the same parameters as seen below. Firebase data
I want to get an array that has each objects country. So if I have 4,000 objects I want to get an array of 4,000 strings all containing a country.
Right now I can get the console to log all the 4,000 objects into an array using the code below.
componentWillMount() {
this.fetchData();
}
fetchData = async () => {
var data1 = [];
var fireBaseResponse = firebase.database().ref();
fireBaseResponse.once('value').then(snapshot => {
snapshot.forEach(item => {
var temp = item.val();
data1.push(temp);
return false;
});
console.log(data1);
});
}
But when I try doing
var fireBaseResponse = firebase.database().ref().child('country');
I get an array of nothing.
Any help would be great.
As mentioned in the comments, you can create a new temp object containing just country before pushing it into your array.
snapshot.forEach(item => {
var temp = { country: item.val().country };
data1.push(temp);
return false;
});
I've read several posts on the subject, but unfortunately struggling with my situation.
I am pulling some urls from an array of urls and then using those links to obtain (let's say) the title of the page from those subsites. At the end I want a list of original urls and an array of titles (from the sublinks). i.e., go into a site/domain, find some links, curl those links to find page titles.
Problem is that my titleArray just returns a Promise and not the actual data. I'm totally not getting closures right and promises. Code runs in node as is. I'm using personal sites in my real code, but substituted common sites to show an example.
const popsicle = require('popsicle');
var sites = ['http://www.google.com','http://www.cnn.com'];
// loop through my sites (here I'm just using google and cnn as a test
for(var i=0;i<sites.length;i++) {
// call function to pull subsites and get titles from them
var titleArray = processSites(sites[i]);
console.log(sites[i] + ": " + titleArray);
}
// get request on site and then get subsites
function processSites(url) {
return popsicle.get(url)
.then(function(res) {
var data = res.body;
// let's assume I get another collection of URLs
// that I pull from the main site
var subUrls = ['http://www.yahoo.com','http://www.espn.com'];
var titleArray = [];
for(var j=0;j<subUrls.length;i=j++) {
var title = processSubSites(subUrls[j])
titleArray.push(title);
}
return titleArray;
});
}
function processSubSites(url) {
return popsicle.get(url)
.then(function(res) {
var data = res.body;
// let's say I pull the title of the site somehow
var title = "The Title for " + url;
console.log(title);
return title;
});
}
The result after running this is:
http://www.google.com: [object Promise]
http://www.cnn.com: [object Promise]
The Title for http://www.espn.com
The Title for http://www.espn.com
The Title for http://www.yahoo.com
The Title for http://www.yahoo.com
whereas it should be:
http://www.google.com: ['The Title for http://www.yahoo.com', 'The Title for http://www.espn.com']
http://www.cnn.com: ['The Title for http://www.yahoo.com', 'The Title for http://www.espn.com']
...
You cannot return normal data from inside a Promise. You need to return another Promise to make it chainable. To process multiple Promise objects in loop, you need to push them in an array and call Promise.all(array);
const popsicle = require('popsicle');
var sites = ['http://www.google.com','http://www.cnn.com'];
var titleArrayPromises = [];
// loop through my sites (here I'm just using google and cnn as a test
for(var i=0;i<sites.length;i++) {
titleArrayPromises.push(processSites(sites[i]));
}
var titleArray = [];
Promise.all(titleArrayPromises).then(function (titleArrays) {
for(var i=0; i<titleArrays.length; i++) {
titleArray.concat(titleArrays[i])
}
// You now have all the titles from your site list in the titleArray
})
function processSites(url) {
return popsicle.get(url)
.then(function(res) {
var data = res.body;
// let's assume I get another collection of URLs
// that I pull from the main site
var subUrls = ['http://www.yahoo.com','http://www.espn.com'];
var titlePromiseArray = [];
for(var j=0;j<subUrls.length;j++) {
titlePromiseArray.push(processSubSites(subUrls[j]));
}
return Promise.all(titlePromiseArray);
});
}
function processSubSites(url) {
return popsicle.get(url)
.then(function(res) {
var data = res.body;
// let's say I pull the title of the site somehow
var title = "The Title for " + url;
return Promise.resolve(title);
});
}
I've been using google's charts API and have reached a dead end. I use the API to query a spreadsheet and return some data. For visualizations I'm using Razorflow - a JS dashboard framework - not Google Charts. Getting the data is pretty straight forward using code like this (this code should work - spreadsheet is public):
function initialize() {
// The URL of the spreadsheet to source data from.
var myKey = "12E2fE8GWuPvXJoiRZgCZUCFhRKlW69uJAm7fch71jhA"
var query = new google.visualization.Query("https://docs.google.com/spreadsheets/d/" + myKey + "/gviz/tq?sheet=Sheet1");
query.setQuery("SELECT A,B,C WHERE A>=1 LIMIT 1");
query.send(function processResponse(response) {
var KPIData = response.getDataTable();
var KPIName = [];
myNumberOfDataColumns = KPIData.getNumberOfColumns(0) - 1;
for (var h = 0; h <= myNumberOfDataColumns ; h++) {
KPIName[h] = KPIData.getColumnLabel(h);
};
});
};
google.charts.setOnLoadCallback(initialize);
The above will create an array holding the column labels for column A,B and C.
Once the data is fetched I want to use the data for my charts. Problem is, I need to have the data ready before I create the charts. One way I have done this, is creating the chart before calling google.charts.setOnLoadCallback(initialize) and then populate the charts with data from inside the callback. Like this:
//create dashboard
StandaloneDashboard(function (db) {
//create chart - or in this case a KPI
var firstKPI = new KPIComponent();
//add the empty component
db.addComponent(firstKPI);
//lock the component and wait for data
firstKPI.lock();
function initializeAndPopulateChart() {
// The URL of the spreadsheet to source data from.
var myKey = "12E2fE8GWuPvXJoiRZgCZUCFhRKlW69uJAm7fch71jhA"
var query = new google.visualization.Query("https://docs.google.com/spreadsheets/d/" + myKey + "/gviz/tq?sheet=Sheet1");
query.setQuery("SELECT A,B,C WHERE A>=1 LIMIT 1");
query.send(function processResponse(response) {
var KPIData = response.getDataTable();
var KPIName = [];
myNumberOfDataColumns = KPIData.getNumberOfColumns(0) - 1;
for (var h = 0; h <= myNumberOfDataColumns ; h++) {
KPIName[h] = KPIData.getColumnLabel(h);
};
//use label for column A as header
firstKPI.setCaption(KPIName[0]);
//Set a value - this would be from the query too
firstKPI.setValue(12);
//unlock the chart
firstKPI.unlock();
});
};
google.charts.setOnLoadCallback(initializeAndPopulateChart);
});
It works but, I would like to separate the chart functions from the data loading. I guess the best solution is to create a promise. That way I could do something like this:
//create dashboard
StandaloneDashboard(function (db) {
function loadData() {
return new Promise (function (resolve,reject){
//get the data, eg. google.charts.setOnLoadCallback(initialize);
})
}
loadData().then(function () {
var firstKPI = new KPIComponent();
firstKPI.setCaption(KPIName[0]);
firstKPI.setValue(12);
db.addComponent(firstKPI);
})
});
As should be quite obvious, I do not fully understand how to use promises. The above does not work but. I have tried lots of different ways but, I do not seem to get any closer to a solution. Am I on the right track in using promises? If so, how should i go about this?
Inside a promise you need to call resolve or reject function when async job is done.
function loadData() {
return new Promise (function (resolve,reject){
query.send(function() {
//...
err ? reject(err) : resolve(someData);
});
})
}
And then you can do
loadData().then(function (someData) {
//here you can get async data
}).catch(function(err){
//here you can get an error
});
});
new Promise(resolve => {
google.charts.setOnLoadCallback(resolve);
}).then(getValues);
Basically I'm making a nice and simple mobile web app for a couple of my friends. It uses some online databases to store position data of shops. I've got the databases working like a charm. No problems there. In fact everything is working except it's all happening in the wrong order I think. The data from the database should be stored in an array and then the objects in that array are displayed on screen. However, using some console logs I've found that the data is being displayed, then being retrieved from the database, then the arrays are filled. But no matter what I do, I can't get it to work! Here is my code:
var latOfSpots;
var lngOfSpots;
var nameOfSpots;
var spotArray;
var spotLatLng;
var spotCollection;
var markers;
var Spot;
var spot;
function init() {
//-------------------------- INITIATE SPOT VARIABLES ---------------------------//
map = new google.maps.Map2(document.getElementById("map"));
latOfSpots= new Array(51.14400,51.02295);
lngOfSpots= new Array(0.25721,0.26450);
nameOfSpots= new Array('Tescos', 'Sainsburys');
spotLatLng= new Array();
markers= new Array();
Spot = Parse.Object.extend("Spot");
spot = new Spot();
//----------------- GET DATA FROM THE PARSE.COM DATABASE ---------------------//
//---------------------- DISPLAY ARRAY DATA ON MAP ---------------------------//
GetData();
DisplayData();
//----------------------- SET MAP SETTINGS -----------------------------------//
map.setCenter(spotLatLng[0],8);
//map.addControl(new google.maps.LargeMapControl());
map.addControl(new google.maps.MapTypeControl());
}; //END OF INIT FUNCTION ------------------------------------------------//
google.setOnLoadCallback(init);
//------------------- PRIMARY FUNCTION TO GET DATA FROM DATABASE ---------------//
function GetData()
{
var query = new Parse.Query(Spot);
spotCollection = query.collection();
spotCollection.fetch({
success: function(spotCollection) {
// spotCollection.toJSON()
// will now be an array of objects based on the query
FillArrays();
console.log('data retreived' + spotCollection);
}
});
}
//----------------- FUNCTION TO LOAD DATABASE INTO ARRAYS -------------------//
function FillArrays()
{
spotArray = spotCollection.toJSON();
for (var j = 0; j<spotArray.length; j++)
{
latOfSpots.push(spotArray[j].Latitude);
lngOfSpots.push(spotArray[j].Longitude);
nameOfSpots.push(spotArray[j].Name);
}
}
//------------------------ FUNCTION TO DISPLAY ALL ARRAY DATA ONSCREEN -----------------//
function DisplayData()
{
for(var i = 0; i<latOfSpots.length; i++)
{
spotLatLng[i] = new google.maps.LatLng(latOfSpots[i], lngOfSpots[i]);
for(var x = 0; x<latOfSpots.length; x++)
{
markers[x] = new google.maps.Marker(
spotLatLng[i], {
"draggable":false,
"title":nameOfSpots[i],
});
map.addOverlay(markers[x]);
}
}
console.log('data displayed');
}
Your database query is asynchronous. You need to use the data in the Get_Data callback function (after it has come back from the server). Currently you are attempting to use it before the server sends it back.
//------------------- PRIMARY FUNCTION TO GET DATA FROM DATABASE ---------------//
function GetData()
{
var query = new Parse.Query(Spot);
spotCollection = query.collection();
spotCollection.fetch({
success: function(spotCollection) {
// spotCollection.toJSON()
// will now be an array of objects based on the query
FillArrays();
console.log('data retreived' + spotCollection);
DisplayData();
}
});
}