synchronization with pouchdb and couchdb - javascript

I would like to do a progress bar for the time when the database synchronize. The request which counts the number of documents to synchronize is too long. I tried with the request GET _active_tasks on the couchdb database but it returns an empty json. I tried with the change event of the Pouchdb function replicate but the info variable doesn't display. Have you others technics for the progress bar or would you know how used the technics I have ever tried ?

I have not found a perfect solution, but one that seemed 'good enough' for us has been
get info about source db, to know what the 'end goal' is.
Add a 'changes' callback (like you mentioned in your answer), where you receive an info object with the last_seq that has been replicated. Divide this with the update_seq you got from the source, and update your progress bar.
~
Q.all(source.info())
.then(function(sourceInfo) {
var replication = source.replicate.to(target);
var startingpoint;
replication.on('change', function(info) {
// the first time we get a replication change,
// take the last_seq as starting point for the replication
// and calc fractions based on that
var fraction = 0;
if(typeof startingpoint === "undefined") {
startingpoint = info.last_seq;
} else {
fraction = (info.last_seq - startingpoint) / (sourceInfo.update_seq - startingpoint);
}
// Whatever you need to do to update ui here
updateUi(fraction);
});
})

Related

evernote findNotesMetadata - using offset and maxnotes to loop to retrieve all notes

Per Evernote documentation for findNotesMetadata the maxnotes returned from server in 1 response is 250. I am trying to understand how to make multiple requests to retrieve entire array if more then 250. Below is current code.
const Evernote = require('evernote');
const developerToken = "...";
const client = new Evernote.Client({token: developerToken, sandbox: false});
const noteStore = client.getNoteStore();
const spec = {}
spec.includeTitle = true;
spec.includeTagGuids = true;
spec.includeAttributes = true;
spec.includeNotebookGuid = true;
const filter = new Evernote.NoteStore.NoteFilter({
words: '*',
});
noteStore.findNotesMetadata(filter, 0, 250, spec)
.then(noteobj => {
...
})
.catch( e => console.error(e));
Current code doenst incorporate any loop yet but works up to 250 notes. Due to Evernote SDK and dealing with promises Im not positive even where to start. I have searched online quite a bit to find a solution directly (looking at Evernote examples) and indirectly (looking at other rest API examples). Not having any luck. Any help is appreciated.
The offset param to findNotesMetadata is how you indicate the start index into the actual result set you want. In the case of the code you've shown, you're passing in 0 (it's the second param). That is telling the API that you want your results to begin with item 0 in the actual result set, up to a maximum of 250 results.
If you want to "page" through the result set in windows of 250 results, you can call the method again using 250 as the offset, and ask for the next 250 results. This is a fairly common design pattern for paging through result sets via a remote API or anything that has a resource constraint on retrieving data. You'll want to handle the cases when no more results are available-- either because you get fewer back than the maxNotes that you ask for or the corner case where you get exactly the max number but then zero on the following request. That's how you know to break out of your loop.
The Evernote API seems to offer a findNoteCounts method, which should give you an idea of how many actual results there would be, but as with all async systems, there's a theoretical race where that number changes between API calls.

Firebase JavaScript value Change Events

I am wondering how i can solve the following issue. I have a Record in the Firebase DB which i am monitoring. The App is a Sports Score So far so good.
When user loads the initial page i check if Game is Running or Stopped and so a few things.
below is a snipped of what i do
if(Clock.Status=='Running'){
......
}
else if(Clock.Status == 'Stopped'){
.......
}
So far so good when user hits the page for first time. But now i want to monitor if the ClockStatus changes
clockStatusRef = firebase.database().ref("games/"+gameId+"/Score/");
clockStatusRef.on("child_changed", function(snapshot) {
var Clock = snapshot.val();
var status = Clock.Status;
// clock stopped - second scenario
if(status=='Stopped'){
stopTimer();
}
else if(status == 'Running'){
// clock status running- third scenario
firebase.database().ref('/.info/serverTimeOffset')
.once('value')
.then(function stv(data) {
console.log('hi');
serverTime = (data.val() + Date.now())/1000;
var timeElapsed = serverTime - Clock.ClockStart;
var totalCounts = document.getElementById("total_counts");
if(Clock.Timer > timeElapsed){
initTimer(Math.floor(Clock.Timer- timeElapsed),60);
}
else{
var Current_Clock = document.getElementById("count");
Current_Clock.innerHTML = '00:00';
}
}, function (err) {
return err;
});
}
console.log("Clock status changed: "+status);
});
for some strange reason on a change of status it starts with the main if
if(Clock.Status=='Running')
So i am wondering what am i missing and what is the best way to fix this so the first if is only run on the initial load and all subsequent will use the if's which handle status change of clock.
Here is the Json for games/B8120ACD-DF51-A64A-A83E-556007522E80/Score/Clock
{
"ClockStart" : 1510535632,
"Period" : 1,
"Status" : "Stopped",
"Timer" : 900
}
You're listening one level higher in your JSON than your code expects.
Either change the code that gets the clock from the snapshot to:
var Clock = snapshot.val().Clock;
Or (better, because it requires less data transfer) listen one level lower in the tree:
clockStatusRef = firebase.database().ref("games/"+gameId+"/Score/Clock");
As there seem to be some limitation as far as what is triggered when multiple listeners looking for changes and data overlaps i changed my code. As my App does not have any heavy traffic so changes are not that often, i use one listener for changes and to address my issue i just went ahead and added the run once for the initial setup then run different code on updates. Would have been nice to control what listener gets the notification of change, also the child_changed seems to have its limitations as i got it to fire but was not able to tell which child actually changed.

"Seen By" feature in Facebook groups

I want to implement a post seen by feature like in FB groups using JS and PHP , I managed to get the seen counts from the scrolling actions but I need to know whether the user just scrolled it down or actually spending time to read it ( some kind of a scroll speed tracker or something similar)
var winTop = $(this).scrollTop();
var $divs = $('.singlePost');
var top = $.grep($divs, function(item) {
return $(item).position().top <= winTop;
});
if (top.length > 0) {
var len = top.length;
var viewingPost = top[len-1]
if( ! $(viewingPost).hasClass("seen")){
var seenData = {"name":"postId", "value":$(viewingPost).attr('data-sharedId')}
parseSeenData( seenData ,viewingPost );
}
}
above is the code which I did to get the seen count,need to get some info regarding user spent enough time on each post to read it.
You could use some sort of timer that times how long each post is "seen" before you actually set it as seen.
Maybe this will help?
I'm thinking you could use something like setTimeout(), and add a view duration property to each post. Use setTimeout to increase the view duration on whatever post is being looked at by one second, every second, and then, after it reaches the value you want, set that post as "seen". Hope this helps, and good luck.

What is more effective: every time make an ajax request or slice a result in func?

I have a JSON data of news like this:
{
"news": [
{"title": "some title #1","text": "text","date": "27.12.15 23:45"},
{"title": "some title #2","text": "text","date": "26.12.15 22:35"},
...
]
}
I need to get a certain number of this list, depended on an argument in a function. As I understand, its called pagination.
I can get the ajax response and slice it immediately. So that every time the function is called - every time it makes an ajax request.
Like this:
function showNews(page) {
var newsPerPage = 5,
firstArticle = newsPerPage*(page-1);
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
var newsArr = JSON.parse(xhr.responseText),
;
newsArr.news = newsArr.news.slice(firstArticle, newsPerPage*(page));
addNews(newsArr);
}
};
xhr.open("GET", url, true);
xhr.send();
Or I can store all the result in newsArr and slice it in that additional function addNews, sorted by pages.
function addNews(newsArr, newsPerPage) {
var pages = Math.ceil(amount/newsPerPages), // counts number of pages
pagesData = {};
for(var i=0; i<=pages; i++) {
var min = i*newsPerPages, //min index of current page in loop
max = (i+1)*newsPerPages; // max index of current page in loop
newsArr.news.forEach(createPageData);
}
function createPageData(item, j) {
if(j+1 <= max && j >= min) {
if(!pagesData["page"+(i+1)]) {
pagesData["page"+(i+1)] = {news: []};
}
pagesData["page"+(i+1)].news.push(item);
}
}
So, simple question is which variant is more effective? The first one loads a server and the second loads users' memory. What would you choose in my situation? :)
Thanks for the answers. I understood what I wanted. But there is so much good answers that I can't choose the best
It is actually a primarily opinion-based question.
For me, pagination approach looks better because it will not produce "lag" before displaying the news. From user's POV the page will load faster.
As for me, I would do pagination + preload of the next page. I.e., always store the contents of the next page, so that you can show it without a delay. When a user moves to the last page - load another one.
Loading all the news is definitely a bad idea. If you have 1000 news records, then every user will have to load all of them...even if he isn't going to read a single one.
In my opinion, less requests == better rule doesn't apply here. It is not guaranteed that a user will read all the news. If StackOverflow loaded all the questions it has every time you open the main page, then both StackOverflow and users would have huge problems.
If the max number of records that your service returns is around 1000, then I don't think it is going to create a huge payload or memory issues (by looking at the nature of your data), so I think option-2 is better because
number of service calls will be less
since user will not see any lag while paginating, his experience of using the site will be better.
As a rule of thumb:
less requests == better
but that's not always possible. You may run out of memory/network if the data you store is huge, i.e. you may need pagination on the server side. Actually server side pagination should be the default approach and then you think about improvements (e.g. local caching) if you really need them.
So what you should do is try all scenarios and see how well they behave in your concrete situation.
I prefer fetch all data but showing on some certain condition like click on next button data is already there just do hide and show on condition using jquery.
Every time call ajax is bad idea.
but you also need to call ajax for new data if data is changed after some periodic time

Using window.setTimeout() and window.setInterval() in this situation

This might be a newb question but....
Recently, I have been using window.setTimeout which makes a recursive call to the parent function, which makes an ajax poll to the server.
function connectToVM(portal) {
//making the ajax call here....
if(response.responseText !== "")
{
windowInterval = window.setTimeout(function() {
connectToVM(portal)
}
, 4000);
}
}
windowInterval is my global var here.
if(!checkIfChartExists()) {
window.clearInterval(windowInterval);
}
Now, instead of making use of variables here, I know that I can simple pass the function to clearTimeout, but that also causes all the other intervals to be stopped :(
The reason why I am doing this is the server does a timeout, only when there is a response.
My scenario is, I have a chart which updates every timeout interval.
AFAIK, when we set the interval, there is a specific value set to the variable(if set to a variable). So when I print my variable(every time when the timeout function is called), I get some int values which are unique.
I have many tabs, and many tabs can have same chart.. which just makes use of the same interval which is triggered earlier.
Now I have just 1 chart.. But I have many charts to show which are of the same type. Say gauge Chart.
I also have to clear the timeout whenever there is no chart present in the current selected tab - which I am doing.
So I am planning to make just 1 function which just makes the call to the server by passing in the required params to this function.
But in order to poll, I am using window.setTimeout thing I mentioned above.
This works for 1 chart.
Now, I try to add 1 more chart, with different set of params to poll the server, I will need to make use of some different setTimeout function, which has a id different than that of the earlier triggered timeout.
I also have to consider that if the 1st chart is already present, the timeout is already triggered and have to keep it running.
So, now I have to trigger the second timeout.
But there is no second timeout here.
I was wondering if there is any alternate approach to this, as I can't really predict how many chart's there will be on runtime.
Question 1 : Can we flood our browser with many timeout's?
Question 2 : How to get the id of that particular timeout, so that I can clearTimeout(id) on it?
Question 3 : Since we can't assign / make variables on the fly, how to set / make such a data structure which can hold such a pointer to the particular chart's index / id.. so that we can easily get hold of it and clear it.
Question 4 : Is this the only way we can poll the server(via AJAX) if we have to poll continually?
Lastly, I recognize this is a very complex issue I have posted in here. But I am sure I will find some useful information about the approach from the forums.
I don't have much experience doing all these stuffs in JS, but any help is appreciated!
Update
Sorry I have to post my code in here.. But I am using Extjs to get my chart portlets. My code for the function connectToVM is this :
function connectToVM(portalId, host, port, user, passwd, db) {
try{
if(Ext.getCmp(portalId))
{
var gaugeChartForTitle = Ext.getCmp(portalId);
if(typeof portalOriginalTitle === 'undefined')
portalOriginalTitle = gaugeChartForTitle.title;
var gaugeChartDiv = document.getElementById(portalId);
Ext.Ajax.request({
url: "/connectToVM?" +
Ext.urlEncode({
host: host,
port: port,
user: user,
passwd: passwd,
db: db
}),
method: 'GET',
success: function (response, options) {
if(response.responseText !== "")
{
gaugeChartDiv.style.background = "";
gaugeChartForTitle.setTitle(portalOriginalTitle);
console.log("Virtual Machine at "+ host +" : BUSY % : "+response.responseText);
virtualMachineStore.loadData(generateVirtualMachineData(response.responseText)); //Setting the data1 value of the store and loading it for display!
windowInterval = window.setTimeout(function() {
connectToVM(portalId, host, port, user, passwd, db)
}
, 4000);
}
else
{
windowInterval = window.setTimeout(function() {
connectToVM(portalId, host, port, user, passwd, db)
}
, 10000); //Retry every 10 seconds to check if the connection is established!
gaugeChartDiv.style.background = "red";
gaugeChartForTitle.setTitle(portalOriginalTitle +" - Connection Failure. Reconnecting!");
}
},
failure: function ( result, request) {
}
});
}
}
catch(err) {
}
}
Now, I trigger my function using this :
function setWindowIntervalForVM(portalId) {
//console.log("isIntervalActivated inside setWindowIntervalForVM() : "+isIntervalActivated);
if(!isIntervalActivated) {
connectToVM(portalId, host, port, user, pwd, db);
}
}
function checkIfWindowIntervalIsActivated(portal) {
if(!isIntervalActivated) {
setWindowIntervalForVM(portal.id);
isIntervalActivated = true;
} else {
window.clearInterval(windowInterval);
windowInterval = null;
isIntervalActivated = false;
}
}
So checkIfWindowIntervalIsActivated() is my parent function call which I call in these scenarios :
1) Whenever the Gauge Chart is newly created.. I Trigger this call and have a boolean isIntervalActivated which if it is false, triggers the server poll.
2) So now if I have the chart already in tab 1(since the user selected it), I now change to tab 2 which does not have it. So I simply set isIntervalActivated to true which stops the poll. This is handled for 1 chart. Now the question here is, if I want to make this function re-usable, say I want to drop one more chart of same type but with different server parameters to poll, how to make use of the same windowInterval variable which has my 1st chart's triggered timeout value. P.S: The value changes for every ajax request it makes. So there'z no 1 single value :(
3) I stop the poll whenever there is no chart of same type present.. in other tab. which makes perfect sense. Now, I am caching all my portlets whenever user drops in a new portlet / on the page load, pulling all the user configured portlets. In such a case, I have to trigger all of the charts' ajax calls.. each polling to its configured destination. Now, I do not know how many charts there will be, as in my function name, I am polling to VM's. So if the user consumes VM1, it switches to VM2 and so on.
So it's absolutely impossible to just create same function for many such similar charts.
So just wanted to check if I can re-use the same timeOut thing, or take a totally different approach to this problem :( :(
I hope it's a bit clear now, if not I can explain my situation more.
Please ask me more questions if required :)
Thanks again!
If I understood correctly and you're trying to support multiple charts updating concurrently, I'd switch from keeping the chart data inside the connectToVM() closure to an explicit array of chart objects and use a single interval to update all charts.
Something like the following (treat it as pseudo-code):
var charts = [
// an array of chart objects, see addChart()
];
function addChart() {
// when you need to add or remove a chart, update the charts object, like this:
charts.push({
update: updateChart,
nextUpdateTime: null, // or Date.now() if you don't care about old browsers.
chartData: {host: ..., port: ..., user: ..., passwd: ..., db: ...,
originalTitle: ..., portalId: ...},
});
restartUpdates();
}
var activeInterval = null;
function restartUpdates() {
if (activeInterval) {
clearInterval(activeInterval);
}
activeInterval = setInterval(updateCharts, 5000);
}
// updates all active charts
function updateCharts() {
var now = new Date().getTime();
for (var i = 0; i < charts.length; i++) {
var chart = charts[i];
if (chart.nextUpdateTime !== null && chart.nextUpdateTime < now) {
chart.nextUpdateTime = null; // chart.update() will re-set this
try {
chart.update(chart);
} catch(e) {
// handle the error
}
}
}
// update a single chart.
// #param |chart| is an item from the |charts| array.
function updateChart(chart) {
// ...same as your connectToVM() using properties from chart.chartData...
Ext.Ajax.request(
// ...
success: function (response, options) {
// ...same as before...
// ...but instead of re-setting the timeout:
// windowInterval = window.setTimeout(function() {
// connectToVM(portalId, host, port, user, passwd, db)
// }
// , 4000);
// ...update the chart's nextUpdateTime:
chart.nextUpdateTime = (new Date().getTime()) + 4000;
}
);
}
initial answer below
Thanks for the detailed question! It feels you're missing something very obvious wrt questions #2/3, but it's hard to tell what specifically without seeing more of your code. Can you post a more complete, yes simple example demonstrating the problem you're trying to solve? Perhaps the function handling changing the active tab in pseudocode would help, like this:
function selectTab(tabID) {
// ...activate tab #tabID in the GUI...
if (tabID == 1) {
// there's chart #1 on tab #1, need to stop any active timeouts and start a new one
connectToVM("chart #1");
} else if (tabID == 2) {
// no charts on tab #2.. need to stop any active timeouts
} else if (tabID == 3) {
// ...
}
}
One thing I don't understand is whether there's always a single chart, that needs updating, at any point of time?
Also, do you know the concepts mentioned in A re-introduction to JavaScript, specifically objects?
As for the questions:
1: yes, too many timeouts should be avoided (thousands a second will probably make the CPU hot and the browser sluggish), although I'd be more worried about the server, which has to handle the requests from multiple clients.
2/3: see above.
4: The Comet page lists a lot of alternatives to basic AJAX polling (server-sent events, long-polling, websockets), but I'd worry about this later.
Yes
var x = window.setTimeout(...); window.clearTimeout(x);
Store it as a data attribute on the active tab, a property on your object, or as a global variable. Many different ways. Example code would have made it easier to answer this.
Based on your comments:
var windowInterval;
function connectToVM(portal) {
if(windowInterval)window.clearTimeout(windowInterval);
windowInterval = window.setTimeout(function() { ... }, 4000);
}

Categories