Handling loop with nodejs asynchronous callback - javascript

I'm new to nodejs and mongoose.
I have a database dated from 2009 until now and would like to count number of data of each month,
and return as json array. Slow async callback results all dates as Aug. 1, 2014
What is the proper way to implement this?
var dbURL = 'mongodb://localhost/database';
var db = require('mongoose').connect(dbURL);
var c_db = require('./models/models.js').c_db;
var start_date = new Date(2009,0,1);
end_date = new Date(2014,8,1),
next_date = new Date();
var test_json=[];
var total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth());
var next_date = start_date;
for(var i=0;i<total_months;i++){
var firstDay = new Date(next_date.getFullYear(), next_date.getMonth(), 1);
var lastDay = new Date(next_date.getFullYear(), next_date.getMonth() + 1, 0);
next_date.setDate(lastDay.getDate()+1);
c_db.count({'shipdate':{'$gte':new Date(firstDay),'$lte':new Date(lastDay)}},function(err,query){
var item = {
"Date": firstDay,
"Count": query
}
test_json.push(item);
});
}
setTimeout(function(){
console.log(test_json);
},5000);

Be careful when you are writing javascript with async callbacks. What you want to do is to continue to the next item in the loop when the current async is finished. You can use a the "async" module: https://github.com/caolan/async
var async = require("async");
var dbURL = 'mongodb://localhost/database';
var db = require('mongoose').connect(dbURL);
var c_db = require('./models/models.js').c_db;
var start_date = new Date(2009,0,1);
end_date = new Date(2014,8,1),
next_date = new Date();
var test_json=[];
var total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth());
var next_date = start_date;
async.timesSeries(total_months, function(n, next) {
var firstDay = new Date(next_date.getFullYear(), next_date.getMonth(), 1);
var lastDay = new Date(next_date.getFullYear(), next_date.getMonth() + 1, 0);
next_date.setDate(lastDay.getDate()+1);
c_db.count({'shipdate':{'$gte':new Date(firstDay),'$lte':new Date(lastDay)}},function(err,query){
var item = {
"Date": firstDay,
"Count": query
}
test_json.push(item);
next();
});
}, function(e) {
console.log(test_json);
});

Related

How can I Make Use of Only One Function with My Weather App

In my weather app, I need to get the user location, which I'm getting from ipinfo.io, so that's one http request, and then I make another http request to another api on openweathermap.org. My question is how can I improve my code. Is it possible to make only one http request function and use it for calling both api by passing different parameters. Notice that I do set a number of variables inside each function which are particular to that function. I don't think it is possible to use these variables outside the scope of the function.
Here's my index.js
/*
Weather App Javascript code
author: George Louis
date: 3/11/2018
purpose: get local weather
*/
window.onload = function() {
//variables
var ipUrl = "https://ipinfo.io/json";
var appid = "appid=8e1880f460a20463565be25bc573bdc6";
var location = document.getElementById("location");
var currentDate = new Date();
var dayNight = "day";
//setting the date
var dateElem = document.getElementById("date");
var strDate = currentDate.toString();
dateElem.innerHTML = strDate.substring(0, strDate.length-18)
//calling ipinfo.io/json function
httpReqIpAsync(ipUrl);
//request to ipinfo.io/json
function httpReqIpAsync(url, callback) {
var httpReqIp = new XMLHttpRequest();
httpReqIp.open("GET", url, true)
httpReqIp.onreadystatechange = function() {
if(httpReqIp.readyState == 4 && httpReqIp.status == 200) {
var jsonIp = JSON.parse(httpReqIp.responseText)
var ip = jsonIp.ip;
var city = jsonIp.city;
var country = jsonIp.country;
location.innerHTML = `${city}, ${country}`;
var lat = jsonIp.loc.split(",")[0];
var lon = jsonIp.loc.split(",")[1];
console.log(lat+" "+lon)
var weatherApi = `http://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&${appid}`;
//calling openweathermap api function
httpReqWeatherAsync(weatherApi);
}
}
httpReqIp.send();
}
//request to openweathermap.com json
function httpReqWeatherAsync(url, callback) {
var httpReqWeather = new XMLHttpRequest();
httpReqWeather.open("GET", url, true);
httpReqWeather.onreadystatechange = function() {
if(httpReqWeather.readyState == 4 && httpReqWeather.status == 200) {
var jsonWeather = JSON.parse(httpReqWeather.responseText);
console.log(jsonWeather)
var weatherDesc = jsonWeather.weather[0].description;
var id = jsonWeather.weather[0].id;
var icon = `<i class="wi wi-owm-${id}"></i>`
var temperature = jsonWeather.main.temp;
var tempFaren = Math.round(1.8 * (temperature - 273) + 32)
// console.log(tempFaren)
var humidity = jsonWeather.main.humidity;
var windSpeed = jsonWeather.wind.speed;
//converting visibility to miles
var visibility = Math.round(jsonWeather.visibility / 1000);
// console.log(visibility)
//find whether is day or night
var sunSet = jsonWeather.sys.sunset;
//sunset is 10 digits and currentDate 13 so div by 1000
var timeNow = Math.round(currentDate / 1000);
console.log(timeNow + "<" + sunSet +" = "+(timeNow < sunSet))
dayNight = (timeNow < sunSet) ? "day" : "night";
//insert into html page
var description = document.getElementById("description");
description.innerHTML = `<i id="icon-desc" class="wi wi-owm-${dayNight}-${id}"></i><p>${weatherDesc}</p>`;
var tempElement = document.getElementById("temperature");
tempElement.innerHTML = `${tempFaren}<i id="icon-thermometer" class="wi wi-thermometer"></i>` ;
var humidityElem = document.getElementById("humidity");
humidityElem.innerHTML = `${humidity}%`;
var windElem = document.getElementById("wind");
windElem.innerHTML = `${windSpeed}m/h`;
var visibilityElem = document.getElementById("visibility");
visibilityElem.innerHTML = `${visibility} miles`;
}
}
httpReqWeather.send();
}
}
You can use the modern way to request with fetch instead, if you like. You can also take advantage of destructuring. This is what I would do:
function httpReqIpAsync(url, callback) {
fetch(url)
.then(response => response.json())
.then(jsonIp => {
const { ip, city, country } = jsonIp;
location.textContent = `${city}, ${country}`;
const [lat, lon] = jsonIp.loc.split(",");
const weatherApi = `http://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&${appid}`;
return [weatherApi, callback];
})
.then(httpReqWeatherAsync)
}
//request to openweathermap.com json
function httpReqWeatherAsync([url, callback]) {
// ...
Since each request is separate, I think it makes much more sense for them to be in separate functions, rather than consolidating them together.

Google scripts every minute trigger not working

I have the following script
function scraper() {
var url = 'http://gpa.shet.com.aspx';
var sss = SpreadsheetApp.getActiveSpreadsheet();
//var ss = SpreadsheetApp.openById('1im78ip4Wcmb1xbfZs8Lqy3-LP1SU9rC8E5OfKbOjJDg');
//var sss = SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = sss.getSheetByName("Sheet1");
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var response = UrlFetchApp.fetch(url);
var contentText = response.getContentText();
var pr = sheet.getRange('A1:Z1000');
var cstring = contentText.tostring;
var ui = SpreadsheetApp.getUi();
var NHL = "New Agent";
var nlength = contentText.length;
// ui.alert(nlength);
//ui.alert(contentText);
//var g = 5;
var clength = 200000;
///
var temp = contentText;
var count = (temp.match(/New Hot Lead/g) || []).length;
var C6 = sheet.getRange('C6');
var C8 = sheet.getRange('C8');
var C10 = sheet.getRange('C10').getValue();
var C10r = sheet.getRange('C10');
if (count > 0) {
var d = new Date();
var hrs = d.getHours();
var mins = d.getMinutes();
var time1 = hrs + ":" + mins;
if (C6.isBlank() == true) {
C6.setValue(time1);
} else if (C6.isBlank() == false) {
C8.setValue(time1);
}
}
if (count == 0) {
C6.clear();
C8.clear();
}
var time2 = 0.00347222222222222;
if (C10 >= time2) {
var D10 = sheet.getRange("D10");
var alert = "NHLs for more than 5 minutes!";
D10.setValue(alert);
D10.setFontColor('Red');
}
}
Now, the problem is not the code itself, since when I run it manually it does work the way it's expected. My problem is with the time-driven trigger. I have tried to manually set it for every minute, and to add the triggerbuilder code at the end and outside of the function, but it still won't work. What are some suggestions?
Try using the sleep function for 60 seconds.
sleep(60000);

How to pass parameter between two javascript files in express.js

I am using express js and i want to pass parameter from one javascript file to other. How can I achieve this??
The two files are 1. process.js
var WebPageTest = require('webpagetest');
var wpt = new WebPageTest('server address');
var data_url;
exports.process = function (req, res){
//Running the test
wpt.runTest(script,{runs: 1},function(err, data) {
console.log("<----STARTING TEST---->");
if(err){ console.log(err);}
data_url = data.data.summaryCSV;
console.log('-----------');
console.log(data_url);
console.log('-----------');
});
res.render('index.jade',{par: 'welcome to webpagetest performance, the tests are running in background.'})
};
storedata.js is here
var request = require('request');
var CSV = require('csv-string');
var moment = require('moment');
var process = require('./process.js');
exports.storedata = function(req,res){
var URL;
var loadTime;
var TTFB;
var TTFB1;
var date;
var date1;
var date2;
var db;
console.log(process.process.data_url);
request({uri:process.process.data_url,method:'GET'}, function (error,response,body) {
//console.log('----######----');
//console.log(response.headers);
console.log('----######----');
//console.log(response);
if (error) {
console.log('got an error' + error);
}
//console.log(response);
//console.log(body);
var data = body;
console.log('here is the body');
console.log('----######----');
console.log(body);
CSV.forEach(data, ',', function (row, index) {
if (index == 1 || index == 2) {
URL = row[0];
loadTime = row[1];
TTFB = row[2];
TTFB1 = parseInt(TTFB);
date = new Date(row[59] * 1000);
month = date.getUTCMonth() + 1;
month = month.toString();
var day = date.getUTCDate();
day = day.toString();
var year = date.getUTCFullYear();
year = year.toString();
date = year + "-" + month + "-" + day;
date1 = new Date(date);
date2 = moment(date1).format('YYYY-MM-DD');
//console.log(loadTime);
var app_re = new RegExp(/^https\:\/\/some-url/);
var staging_re = new RegExp(/^https\:\/\/some-url2/);
var webuinqa_re = new RegExp(/^https\:\/\/some-url3/);
// Writting into the databse for some-url
if(app_re.test(URL)){
var db = req.db;
var collection = db.get('app');
collection.insert({
"Date": date2,
"TTFB": TTFB1,
"loadTime": loadTime,
"Url": URL
}, function (err, doc) {
if (err) {
res.send("There was a problem adding the information to the database.");
}
});}
//Writting into the database for some-url2
if(staging_re.test(URL)){
var db = req.db;
var collection = db.get('staging');
collection.insert({
"Date": date2,
"TTFB": TTFB1,
"loadTime": loadTime,
"Url": URL
}, function (err, doc) {
if (err) {
res.send("There was a problem adding the information to the database.");
}
});}
//Writting into the database for some-url3
if(webuinqa_re.test(URL)){
var db = req.db;
var collection = db.get('webuinqa');
collection.insert({
"Date": date2,
"TTFB": TTFB1,
"loadTime": loadTime,
"Url": URL
}, function (err, doc) {
if (err) {
res.send("There was a problem adding the information to the database.");
}
});}
res.render('index', {title: "All the test Results have been added to the databases, Go to localhost/getData to get the graph"});
//res.redirect('/getData');
}
});
});
};
I want to pass parameter data_url in process.js file to storedata.js file so. I will use the value of data_url in method request in storedata.js.
You could try something like this:
In your storedata.js
module.exports = function(data_url) {
// ...
}
In process.js:
var request = require('request');
var CSV = require('csv-string');
var moment = require('moment');
// The path like this assumes storedata.js and process.js
// are in the same folder.
var storeData = require('./storedata');
exports.process = function (req, res){
var URL;
var loadTime;
var TTFB;
var TTFB1;
var date;
var date1;
var date2;
var db;
var data_url;
// initiating the test
var WebPageTest = require('webpagetest');
var wpt = new WebPageTest('server-address');
//Running the test
wpt.runTest(script,function(err, data) {
//console.log("hello -->",err || data);
data_url = data.data.summaryCSV;
console.log('-----------');
console.log(data_url);
console.log('-----------');
// Once your data_url is ready
storeData(data_url);
UPDATE:
Based on your comments, here is a possible solution.
var WebPageTest = require('webpagetest');
var wpt = new WebPageTest('server address');
var data_url;
exports.process = function (req, res){
//Running the test
wpt.runTest(script,{runs: 1},function(err, data) {
console.log("<----STARTING TEST---->");
if(err){ console.log(err);}
data_url = data.data.summaryCSV;
console.log('-----------');
console.log(data_url);
console.log('-----------');
});
res.render('index.jade',{par: 'welcome to webpagetest performance, the tests are running in background.'})
};
// Create another method that is able to return the saved data.
exports.getSavedDataURL = function() { return data_url; }
Then in storedata.js
exports.storedata = function(req,res){
var URL;
var loadTime;
var TTFB;
var TTFB1;
var date;
var date1;
var date2;
var db;
//
var url = process.getSavedDataURL();
request({uri:url,method:'GET'}, function (error,response,body) {

How to use a variable as key in json array in javascript

I have following json formate
"[{"tempId":[{"cityName":"London"},{"weather":"overcast clouds"}]}]"
In above format tempId is not a String-value it is a variable.It's value is something like "25Dec2013".But it is inserted as it is mean a name of variable and not a value.
So it should look like
"[{"tempId":[{"25Dec2013":"London"},{"weather":"overcast clouds"}]}]"
I have done following code.I have written one comment in code where the actual problem is.
var arrCityrecordForADay = [];
function getWeatherDataForCities(cityArray, callback) {
var toDaysTimestamp = Math.round((new Date()).getTime() / 1000) - (24 * 60 * 60);
for (var i in cityArray) {
for (var j = 1; j <= 2; j++) {
var jsonurl = "http://api.openweathermap.org/data/2.5/history/city?q=" + cityArray[i] + "&dt=" + toDaysTimestamp;
$.ajax({
url: jsonurl,
dataType: "jsonp",
mimeType: "textPlain",
crossDomain: true,
contentType: "application/json; charset=utf-8",
success: function (data) {
var arrCityRecordForDay = [];
arrCityRecordForDay.push({
"cityName": data.list[0].city.name
}, {
"weather": data.list[0].weather[0].description
});
var tempId = data.list[0].city.name+""+timeConverter(data.list[0].dt);
arrCityrecordForADay.push({
tempId: arrCityRecordForDay // Here tempId is inserted as "tempId" not its value
});
if (((arrCityrecordForADay.length)) === cityArray.length) {
callback(arrCityrecordForADay);
}
}
});
toDaysTimestamp = toDaysTimestamp - (24 * 60 * 60);
}
}
}
$(document).ready(function () {
var cityArray = new Array();
cityArray[0] = "pune";
cityArray[1] = "london";
var result = document.getElementById("msg");
getWeatherDataForCities(cityArray, function (jsonData) {
var myJsonString = JSON.stringify(jsonData);
console.log(myJsonString);
});
});
function timeConverter(UNIX_timestamp){
var a = new Date(UNIX_timestamp*1000);
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var year = a.getFullYear();
var month = months[a.getMonth()];
var date = a.getDate();
var hour = a.getHours();
var min = a.getMinutes();
var sec = a.getSeconds();
//var time = date+','+month+' '+year+' '+hour+':'+min+':'+sec ;
var time = date+''+month+''+year;
return time;
}
How to insert a variable as a key in above example?
EDIT:
And Why output is not stable.Some time wrong and sometime correct.
Here is correct output:
"[{"Pune25Dec2013":[{"cityName":"Pune"},{"weather":"Sky is Clear"}]},{"London22Dec2013":[{"cityName":"London"},{"weather":"overcast clouds"}]}]"
Some times it shows following output after some refresh.
"[{"Pune24Dec2013":[{"cityName":"Pune"},{"weather":"Sky is Clear"}]},{"Pune25Dec2013":[{"cityName":"Pune"},{"weather":"Sky is Clear"}]}]"
How to overcome this?
Your response will be appriciated !!
You have to use a temp variable to achieve this:
var obj = {};
obj[tempId] = arrCityRecordForDay;
arrCityrecordForADay.push(obj);

Problems with Jquery and Javascript SDK of Parse on Safari

I'm new to Jquery and Parse and I don't speak english so first of all sorry for the syntax of the question.
I wrote a function that update my Artist object on parse.com (updateArtist(objectId)). This function is called when I click on Save button and works fine on FireFox and chrome but not on Safari.
function updateArtist(objectId) {
Parse.initialize("myid", "myid");
alert(objectId);
var Artist = Parse.Object.extend("Artist");
var query = new Parse.Query(Artist);
query.equalTo("objectId", objectId);
query.first({
success: function(object) {
// Successfully retrieved the object.
$('#createArtist').css('visibility', 'hidden');
$('.loadingImage').css('visibility', 'visible');
alert('success');
var name = $("#txtName").val();
var link = $("#txtLink").val();
var desc = $("#txtDesc").val();
var place = $("#txtPlace").val();
var latitude = parseFloat($("#txtLat").val());
var longitude = parseFloat($("#txtLong").val());
var eventDate = $('#txtDate').val();
var eventTime = $('#txtTime').val();
console.log(eventDate);
console.log(eventTime);
console.log(name);
console.log(link);
console.log(place);
console.log(desc);
console.log(latitude);
console.log(longitude);
if (eventDate.charAt(2)=='/') {
var dateArray = eventDate.split('/');
var month = dateArray[0] - 1;
var day = dateArray[1];
var year = dateArray[2];
} else if (eventDate.charAt(2)=='-') {
var dateArray = eventDate.split('-');
var month = dateArray[1] - 1;
var day = dateArray[0];
var year = dateArray[2];
}
console.log(month);
console.log(day);
console.log(year);
var timeArray = eventTime.split(':');
var finalDate = new Date(year, month, day, timeArray[0], timeArray[1], 0, 0);
console.log(timeArray);
console.log(finalDate);
var point = new Parse.GeoPoint(latitude, longitude);
console.log(point);
var fileUploadControl = $("#profilePhotoFileUpload")[0];
if (fileUploadControl.files.length > 0) {
var file = fileUploadControl.files[0];
var photoName = "photo.jpg";
var parseFile = new Parse.File(photoName, file);
}
parseFile.save().then(function(){
object.save(null, {
success: function (contact) {
alert('secondo success');
contact.set("name", name);
contact.set("link", link);
contact.set("description", desc);
contact.set("place", place);
contact.set("geoLocation", point);
contact.set("eventDate", finalDate);
contact.set("image", parseFile);
contact.save();
window.location.href = "artist_list.html";
}
});
});
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
}
I'm using Safari 6.0.5 and the alerts and the console.log give me what i want... I'm totally lost..
When you are calling "updateArtist"? Be sure you wait for $(document).ready(function(){…}).

Categories

Resources