Javascript asynchronous for loop - javascript

Is there a way for me run codes asynchronously in a for loop?
In this example, events from day x to y are required to be added into the calendar through a for loop. However the loop is taking roughly a min and its too long, as it is required to go through and add all the days from Jan 4, 2016 to Dec 28, 2020.
Right now, I will have to wait for all the days to be loaded to view the result.
Is there a way for events to get added and appear as soon as the 'addEventSource' is fired / before it goes through all the whole loop. Is it possible to make it asynchronous?
Javascript
$(document).ready(function () {
loadCalendar(null);
var start = new Date("Jan 4, 2016 08:00:00");
var end = new Date("Dec 28, 2020 12:00:00");
var startTime = new Date("Jan 4, 2016 08:00:00");
var endTime = new Date("Jan 4, 2016 12:00:00");
addCalendarEvents("Test", start, end, startTime, endTime);
});
function addCalendarEvents(title, start, end, repeatDays, startTime, endtime) {
var events = [];
var one_day = (24 * 60 * 60 * 1000);
var loopEnd = end.getTime();
for (var loop = start.getTime() ; loop <= loopEnd; loop = loop + one_day) {
var eventDate = new Date(loop);
var tempStart = start;
var tempEnd = end;
tempStart.setDate(eventDate.getDate());
tempStart.setMonth(eventDate.getMonth());
tempStart.setFullYear(eventDate.getFullYear());
tempEnd.setDate(eventDate.getDate());
tempEnd.setMonth(eventDate.getMonth());
tempEnd.setFullYear(eventDate.getFullYear());
$('#calendar').fullCalendar('addEventSource', [{
title: title,
start: tempStart,
end: tempEnd,
allDay: false
}]);
}
}
p.s. $('#calendar').fullCalendar('addEventSource', event) adds events to the calendar.

Javascript doesn't have a threading model, but it does have asynchronous timers.
Check this out: http://www.sitepoint.com/multi-threading-javascript/

As Tibrogargan mentioned, it can be achieved using setTimeout/setInterval.
The idea is to run the for loop for certain time and break the loop. again trigger the loop after certain time from where it has stopped earlier. This way you will not block the user.
eg..
var thresholdTime = 500;
function searchForData(searchTerm, indexFromWhereToSearch) {
var startTime = new Date(),
searchFrom = indexFromWhereToSearch;
for (var i=searchFrom; i < hugeData.length; i++) {
.......
if (newDate() - startTime >= thresholdTime) {
setTimeout((function(index) {
return function() {
searchForData(searchTerm, index);
}
})(i+1), 300/*another threshold*/);
break/return;
}
}
}

Related

List different subrange days from a date range with moment and javascript

I have 2 dates with hours:
Start: 2019-09-06 14:00:00
End: 2019-09-9 19:30:00
I need to list all subrange days (full or partial) inside the range, also with hours, in this example:
2019-09-06 14:00:00 to 2019-09-06 23:59:59
2019-09-07 00:00:00 to 2019-09-07 23:59:59
2019-09-08 00:00:00 to 2019-09-08 23:59:59
2019-09-09 00:00:00 to 2019-09-09 19:30:00
in an array like:
result = array(
0 => array(
"Start" => 2019-09-06 14:00:00,
"End" => 2019-09-06 23:59:59
),
1 => array(
"Start" => 2019-09-07 00:00:00,
"End" => 2019-09-07 23:59:59
),
...
)
I have found similar script to list all days like:
var enumerateDaysBetweenDates = function(startDate, endDate) {
var dates = [];
var currDate = moment(startDate).startOf('day');
var lastDate = moment(endDate).startOf('day');
while(currDate.add(1, 'days').diff(lastDate) < 0) {
console.log(currDate.toDate());
dates.push(currDate.clone().toDate());
}
return dates;
};
But it doesn't consider hour and subrange like I need.
I'd like to use moment.js to simplify all the job but i'm not sure how to start with.
Any suggest how to "recognize" different days?
That was a fun exercise with moment.js. The idea is to collect list of day starts and ends separately:
var start = "2019-09-06 14:00:00";
var end = "2019-09-9 19:30:00";
var startMoment = moment(start);
var endMoment = moment(end);
var starts = [startMoment.toDate()];
var ends = [];
var dayBeforeEnd = moment(endMoment).subtract(1, 'days');
for (var m = moment(startMoment); m.isBefore(dayBeforeEnd); m.add(1, 'days')) {
ends.push(moment(m).endOf('day').toDate());
starts.push(moment(m).add(1, 'days').startOf('day').toDate());
}
ends.push(endMoment.toDate());
Now starts[i] and ends[i] contains corresponding day start and end as Date objects.
One may notice a lot of moment(moment_object) happening. That is because moment objects are mutable, so you need to clone it every time you need to add or subtract some timerange.
You don't need to load moment for that.
In JavaScript, the Date object has setHour(), setMinutes() and so on. You can get the current date, sum 24 hours and get the date again.
For example:
function getRanges(start, end) {
start = new Date(start).getTime(); // Sanitize input
end = new Date(end).getTime();
var list = [];
var current = start;
while(current < end) {
var date = new Date(current); // Get current date
// Set the date to just before midnight.
date.setHours(23);
date.setMinutes(59);
date.setSeconds(59);
date.setMilliseconds(999);
// Now you have the next element in the range
var next = date.getTime();
if (next > end) { // Don't surpass the end
next = end;
}
// create a range using the current and the end of the day before midnight
list.push({
start: current,
end: next
});
current = next+1; // Go to the very next day
}
return list;
}
var ranges = getRanges(Date.now()-(7*24*60*60*1000), Date.now());
// You can convert them to dates if you want
for (var i = 0; i < ranges.length; i++) {
ranges[i].start = new Date(ranges[i].start).toLocaleString();
ranges[i].end = new Date(ranges[i].end).toLocaleString();
}
console.log(ranges);

Adding hours to a Javascript date in a loop

I'm getting some strange results from adding hours to a date. I'm basically adding 0, 6, 12, 18, 24, 30, etc hours to a Javascript date. I came across some of the recommendations online (like this: Adding hours to Javascript Date object?), but when in a loop it was skipping ahead many hours/months. It seemed to be keeping the new version of the date and just adding hours to it...when I really just want to add the hours to the original date.
So, here's the basics of what I have.
for (var i = 1; i < 4; i++) {
hour_date.setHours(hour_date.getHours() + hour);
output.push(hour_date...)
}
//where hour is 6, 12, 18, 24, etc in a loop
//and where hour_date is defined earlier and is
//Sun Apr 02 2017 12:00:00 GMT-0700 (Pacific Daylight Time)
So I'm trying to figure out how to simply add 6 hours to an initial date variable...so I can push those values out to an array. I understand the push part...but I'm just trying to add the hours correctly within the loop.
Thanks very much for any help!
It may be simpler to use the date's raw value and add to it in milliseconds.
Example:
var date = Date.now()
console.log(new Date(date))
var date2 = new Date(date+1000*60*60*6) // Add 6 hours.
console.log(date2)
var date3 = new Date(date+1000*60*60*3) // Add 3 hours.
console.log(date3)
In a loop you'll have to make sure you create new variables from the original variable, not modifying the original. In your case this is easy if you simply create new Date objects and insert them into an array. Use .valueOf() to access the underlying number value of a date object.
var date = new Date();
dates = [date];
for(var i = 6; i <= 30; i += 6) {
dates.push(new Date(date.valueOf() + i * 1000 * 60 * 60));
}
console.log(JSON.stringify(dates, null, 4))
// [
// "2017-04-03T00:57:52.420Z",
// "2017-04-03T06:57:52.420Z",
// "2017-04-03T12:57:52.420Z",
// "2017-04-03T18:57:52.420Z",
// "2017-04-04T00:57:52.420Z",
// "2017-04-04T06:57:52.420Z"
// ]
You need a new object each time. Currently you are modifying the same object over and over and pushing the same reference to each index of the array
Try:
for (var i= 1; i < 4; i++) {
var newDate = new Date(hour_date);
hour += 6;
newDate.setHours(hour_date.getHours() + hour);
output.push(newDate);
}
var hour_date = new Date(), output = [], hour = 0;
for (var i = 1; i < 10; i++) {
var newDate = new Date(hour_date);
hour += 6;
newDate.setHours(hour_date.getHours() + hour);
output.push(newDate);
}
console.log(JSON.stringify(output, null, ' '))
try this instead;
let hours = [6, 12, 18, 24];
let hour_date = new Date;
hours = hours.map(hour=>{
return new Date(hour_date.getTime() + (hour*60*60*1000))
});
console.log(hours);

How to run function() frequently on specific times of the day in javascript

I have a function which runs every 3 minutes 24/7 using setTimeout(). The problem is that it fetches data from an API that have an maximum of request a month. I want to run it as often as a can but it´s unnecessary to do so when i am a sleep because of the waste of requests. How can in addition only run my script between for example 06:30:00 and 20:00:00?
You will need both setTimeout and Date() to achieve this :
for e.g.
var now = new Date();
var millisTill10 = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 10, 0, 0, 0) - now;
if (millisTill10 < 0) {
millisTill10 += 86400000; // it's after 10am, try 10am tomorrow.
}
setTimeout(function(){alert("It's 10am!")}, millisTill10);
For more details please follow this
I have tested and verified following code. Mine is 7:22 PM which comes under these timings and it executes very well.
// get todays strict timings
// 06:30:00 and 20:00:00
setInterval(function() {
lowerDate = new Date();
lowerDate.setHours(6);
lowerDate.setMinutes(30);
lowerDate.setSeconds(0);
upperDate = new Date();
upperDate.setHours(20);
upperDate.setMinutes(0);
upperDate.setSeconds(0);
todayDate = new Date();
if (todayDate > lowerDate && todayDate < upperDate)
console.log("execute"); // execute only if in between these times
}, 3 * 60 * 1000) //Every 3 minutes

flipclock countdown to specific date in specific timezone without reset

I am trying to create countdown to a specific date using flipclock without the timer resetting or people in different time-zones seeing different numbers. For example, I want to countdown to Feb 20, 12:00am MST.
My problem is that the clock resets when the browser is refreshed after it reaches 0, the time shows negative numbers. If people viewing this clock with the current configuration, it is counting down to Feb 20, 12am in their timezone.
I've started with the countdown to New Years compiled clock and set my date, but not sure how else to address the timezone and reset issues.
var clock;
$(document).ready(function() {
// Grab the current date
var currentDate = new Date();
// Set some date in the future. In this case, it's always Jan 1
var futureDate = new Date(currentDate.getFullYear() + 0, 1, 20, 0, 0);
// Calculate the difference in seconds between the future and current date
var diff = futureDate.getTime() / 1000 - currentDate.getTime() / 1000;
// Instantiate a coutdown FlipClock
clock = $('.clock').FlipClock(diff, {
clockFace: 'DailyCounter',
countdown: true,
showSeconds: false,
callbacks: {
stop: function() {
$('.message').html('The clock has stopped!');
}
}
});
});
var clock;
$(document).ready(function() {
// Grab the current date
var now = new Date();
var currentDate = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
currentDate.setHours(currentDate.getHours() - 7);
// Set some date in the future. In this case, it's always Jan 1
var futureDate = new Date(currentDate.getFullYear() + 0, 1, 20, 0, 0);
// Calculate the difference in seconds between the future and current date
var diff = futureDate.getTime() / 1000 - currentDate.getTime() / 1000;
// Limit time difference to zero
if (diff < 0) {
diff = 0;
}
// Instantiate a coutdown FlipClock
clock = $('.clock').FlipClock(diff, {
clockFace: 'DailyCounter',
countdown: true,
showSeconds: false,
callbacks: {
stop: function() {
$('.message').html('The clock has stopped!');
}
}
});
});
Part solving timezone issue (a bit ugly):
// Grab the current date
var now = new Date();
var currentDate = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
currentDate.setHours(currentDate.getHours() - 7);
Part limiting time difference to not less than zero:
// Limit time difference to zero
if (diff < 0) {
diff = 0;
}
Since the time you'd like to count down to is a specific time in a specific time zone, then the easiest way is to pre-convert that time to UTC, and count down to that instead.
On Feb 20th 2016, US Mountain Time is at UTC-7, therefore:
2016-02-20 00:00:00 MST == 2016-02-20 07:00:00 UTC
So,
var currentDate = new Date();
var futureDate = Date.UTC(currentDate.getUTCFullYear(), 1, 20, 7, 0, 0);
var diff = (futureDate - currentDate.getTime()) / 1000;
I'll let someone else answer WRT the specifics of FlipClock and your reset issue - though you might consider asking it in a separate question. (Try to ask only one question at a time in the future.)

How to reinit timer when it end?

everyone! On a website I use this timer, but I do not understand what I need to do when it end. When timer are end it should restart for next 14 days.
You may advice some books, where I can read about my problem or just aboud Date() in js.
Thanks!
There is a callback option for this plugin that is called as soon as you timer ends:
$('#countdown').timeTo({
timeTo: new Date(new Date('Sat Apr 25 2015 09:00:00 GMT+0200')),
displayDays: 2,
theme: "black",
displayCaptions: true,
fontSize: 48,
captionSize: 14,
// important part
callback: function(){
alert('Timer ended');
}
});
When you want to keep track of an user's exprieing time localStorage-API can be used to accomplish this.
Start expiring Timer:
Make a function to keep track of user's expiring date by using localStorage.This function returns the start date when an user visited your site the very first time. This date is used to determine whether an user has already extended the expire time of 14 days but further details are listed below:
function handleUserDate(expireInDays){
var now = new Date();
var startDate = localStorage.getItem('timerStartDate');
// has user already visited your site?
if(startDate){
// is user'date expired?
startDate = new Date(Number(startDate));
var futureDate = new Date(startDate.getTime()+expireInDays*(1000*60*60*24));
if(now.getTime() < futureDate.getTime()){
console.log('in future');
return startDate;
}
}
console.log('in past');
localStorage.setItem('timerStartDate', now.getTime());
return now;
}
Next function is used to activate a timer and putting the number of days that are left into the timeTo option:
function startTimer(inDays){
var now = new Date();
var futureDate = new Date(now.getTime()+inDays*(1000*60*60*24));
console.log(futureDate);
$('#countdown').timeTo({
timeTo: futureDate,
displayDays: 2,
theme: "black",
displayCaptions: true,
fontSize: 48,
captionSize: 14,
callback: function(){
alert('Timer ended');
var daysInFuture = 14;
startTimer(daysInFuture);
}
});
}
A Function to calculate the time difference in days between start date and now:
function getTimeDiff(date, date2, diff){
return Math.abs(date.getTime()-date2.getTime())/diff;
}
Put it all together:
var expireinDays = 14;// 14 day max
var startDate = handleUserDate(expireinDays);
console.log(startDate);// returns date of the very first time or when already expired it returns current date
var now = new Date();
var dayInMill = 1000*60*60*24;
var dayDifference = getTimeDiff(startDate,now,dayInMill);
dayDifference = expireinDays - dayDifference;
console.log(dayDifference); // days left
startTimer(dayDifference); // show timer

Categories

Resources