Google Visualization Query - Abort Request - javascript

I am working on an interface that contains several high-intensity SQL queries, then renders multiple Google charts which are currently being called via AJAX using the google.visualization.Query object:
var query = new google.visualization.Query('/report.ashx');
query.send(callbackMethod);
//....
function callbackMethod(rs){
var data = rs.getDataTable();
var graph = new google.visualization.AreaChart(target_div);
graph.draw(data);
}
As the interface can be filtered dynamically I have encountered a scenario whereby a query can be running, whilst the user could potentially choose to re-filter and hence re-query the data source. If the first query is still running and the second query begins and returns before the first query then the chart will be drawn just fine. However, when the first query finally completes it could completely overwrite the chart with the old data, ignoring the current filters.
I have read that there is the ability to pass a jQuery AJAX object in, which exposes an XHR object allowing me to call .abort() on the XHR which would cancel the request (albeit this would still process on the server, but that's a hit I'm willing to take). Unfortunately I can find no examples of this and the Google documentation is less than helpful in this respect. Has anybody encountered the same, and if so - have they solved the problem?
Cheers,
Chris.

You can wrap callbackMethod in a higher order function to keep track of the request time, and use query.send(callback()) instead of query.send(callbackMethod).
var mostRecentReqTime;
var callback = function() {
var reqTime = Date();
return function() {
if (reqTime < mostRecentReqTime) return;
var data = rs.getDataTable();
var graph = new google.visualization.AreaChart(target_div);
graph.draw(data);
mostRecentReqTime = reqTime;
};
};

Related

Rest API Search Results is not the same as the results returned by the search page

I have A search rest API, when I run it through Share point Designer, i don't Get the Same Number if results as Returned by the Search page on the Share point site, I have tried Using different Source ids , also tried to use the default source id from results source but I always get the same results so i am not sure what I am doing wrong.
My Other Thought is, IS there a way to Get all the results From the Default search function Built in to Share-point?
var ct = new SP.ClientContext.get_current();
var keywordQuery = new Microsoft.SharePoint.Client.Search.Query.KeywordQuery(ct);
var queryStr = ctx.DataProvider.get_currentQueryState().k;
keywordQuery.set_queryText(queryStr);
keywordQuery.set_trimDuplicates(false);
keywordQuery.set_enableSorting(true);
keywordQuery.set_sourceId=("xxxxxx-xxxx-xxxx-xxx-xxxxxxx");
keywordQuery.set_rowLimit(500);
keywordQuery.set_trimDuplicates(false);
var searchExecutor = new Microsoft.SharePoint.Client.Search.Query.SearchExecutor(ct);
var results = searchExecutor.executeQuery(keywordQuery);
ct.executeQueryAsync(onQuerySuccess, onQueryFail);
function onQuerySuccess()
{
results.m_value.ResultTables[1].ResultRows.forEach(function (row)
{
var Aname1 = row.name;
console.log(row);
if (!$isNull(Aname1))
{
var name= Aname1;
console.log(name);
}
});
}
function onQueryFail()
{
}
Usually, the results are paginated. What it means is that, instead of returning all the results at once, they are divided into parts and each part (page) is sent once.
For example, when you search in google.com, instead of returning all 1,50,00,000.... results, Google returns only 10 results or so. To get the next 10 results, you click the next button in the pagination menu at the bottom of the page.
This is done so that the API and network don't get overloaded. Imagine how large a response with 1,50,00,000 records would be.
This is what's happening with you. In the response you recieved, see if there's a record with a URL for the next page, Microsoft usually does things this way. If you call that URL, you'll get the next page. If that's not there, see if the URL you called has a parameter somewhere, where you can select the page.

Limit GET requests (D3.js/Twitter API)

I am currently using D3.js and have modified my chart from listening to mouseover/mouseout to mousemove. This has brought quite a few issues in the chart but none moreso than my GET statuses/show/:id requests.
Previously, I would have points on my chart to hover over and if there was a tweet within half an hour of that point (from a tweet DB in backend), it would send a GET request to get that tweet.
My problem now is that because I'm using mousemove in proximity to these points on my chart as opposed to mouseover, its firing this hundreds of times and the GET requests are limited to 900 in a 15-minute window.
var tweet_arr = [];
for(j in data_tweets){
var tweet_time = timeParser(data_tweets[j]['timestamp_s']);
var point_time = timeParser(d.timestamp);
var diff = point_time.getTime() - tweet_time.getTime();
if(diff<=1800000 && diff>=-1800000) {
tweet_arr.push(data_tweets[j]);
} else {
var tweet_list = []
d3.selectAll(".panel-body")
.data(tweet_list)
.exit()
.remove();
}
}
twitterapi.fetch().getTweets(tweet_arr, tweet_urls[0], tweet_urls[1]);
This function checks the difference between the nearest point on the x-axis and checks my collection of tweet data, if there is one in half an hour, add it to an array called tweet_arr and then pass that into my fetch() function which has an AJAX call to the Flask framework where I run my GET request by ID.
What I would ideally want it to do is have some check that if the request to fetch a specific tweet has been carried out in say, the last 5 seconds, don't run the fetch() function.
How would I go about doing something like this?
Have a look at debounce and throttle from underscore.js: http://underscorejs.org/#debounce,
http://underscorejs.org/#throttle
Here's a good, short post about debouncing requests: https://www.google.de/amp/s/davidwalsh.name/javascript-debounce-function/amp
For a comparison between throttle and debounce, see https://gist.github.com/makenova/7885923
You need to define your fetch logic in a separate function and put that one into _.debounce.
Have a look at this example: https://codepen.io/anon/pen/EQwzpZ?editors=0011
const fetchFromTwitter = function(s) { console.log(s) }
var lazyFetch = _.debounce(fetchFromTwitter, 100)
lazyFetch('This is')
lazyFetch('is')
lazyFetch('gonna be')
lazyFetch('legen ... ')
lazyFetch('wait for it')
lazyFetch('... dary')
lazyFetch('LEGENDARY')

Custom Tab in the Field Service Schedule Board

I found this blog: http://www.powerobjects.com/2016/08/01/advanced-customizations-for-the-custom-tab-in-the-field-service-schedule-board/#collapse2
In it the author describes using configuration to create a new tab in the Field Services Schedule Board by pointing it to a CRM web resource.
The blog includes the following javascript:
function updateBooking()
{
var entityRecordGuid = "10B8A40B-D499-E611-80E6-A45D36FC5A4C";
// GUID is hardcoded to make the sample code easier to understand.
// We can extend this customization to be able to extract the selected booking IDs
// from the SChedule Board's DOM, but that is out of scope for now
var bookableResourceBooking = new XrmServiceToolkit.Soap.BusinessEntity("bookableresourcebooking", entityRecordGuid);
bookableResourceBooking.attributes["cus_urgency"] = document.getElementById('UrgencyInput').value;
bookableResourceBooking.attributes["cus_notes"] = document.getElementById('NoteInput').value;
var updateResponse = XrmServiceToolkit.Soap.Update(bookableResourceBooking);
if (updateResponse == "") { // clear fields if synced to crm
document.getElementById('UrgencyInput').value = "";
document.getElementById('NoteInput').value = "";
} else {
alert('Data didn't sync to CRM');
}
}
The problem that I've got is that I'm not sure how to get the entityRecordGuid value dynamically.
There doesn't seem to be a way of configuring the web resource to
have the selected Item as part of the querystring
There seem to be undocumented JavaScript libraries for Field
Services; however, I can't access them from the web resource IFrame
and of course, they're undocumented.
Has anyone else tried to do this? I'm using CRM Online
I ended up doing this by scraping the HTML directly rather than trying to use any of the API methods from Field One.
This wasn't really a satisfactory answer for me. It depends on the Unscheduled Orders board being in a certain order and since this is changeable by the end-user my solution is very fragile.
For anyone else looking, I did manage to find these API methods; however, I couldn't find any documentation for them so assume that they are unsupported. I also couldn't tie them together to achieve what I wanted
// get the id of the sub grid
F1SDK.SchedulerPage.UnscheduledOrdersGrid.id
// -> "UnscheduledGrid"
F1SDK.SchedulerPage.UnscheduledOrdersGrid.getItemId()
// -> "UnscheduledGrid"
F1SDK.SchedulerPage.UnscheduledOrdersGrid.getStore().storeId
// -> "UnscheduledWorkOrders"
F1SDK.SchedulerPage.UnscheduledOrdersGrid.getStore().data.items[0].internalId
F1SDK.SchedulerPage.UnscheduledOrdersGrid.selModel.selected.items[0].internalId
// Get a subgrid
FieldOneSkyUtils.Subgrid.GetSubgrid('id')
F1SDK.data.models.WorkOrder.getFields()
F1SDK.data.models.WorkOrder.getIdByWONumber('00106')
// -> {55caa97d-429a-e611-80e6-c4346bc4bef0}

AJAX progress bar on array iteration?

I am not too familiar with AJAX but I'm sure what I am trying to do is possible.
Basically I have a form with a text area, when the form is submitted the text area is made into an array with each new line being a value. Simple stuff, now my php then performs a database query on each array value. Also simple.
Now as the operation takes a while I want to make it into an AJAX call using jquery, and for every iteration on the array I want it to display the result back on my main page as well as displaying a progress bar.
So if my text area contains a list of 20,000 names and the query is to fetch the ages of these people, the ajax call would split the textarea into an array and iterate the array. For each iteration it should perform the query and send the result to my main page. So on my main page I will see a list that grows over time.
I hope I have explained this well enough, I just need advice on where to start/what to research. Any examples would be greatly appreciated.
Thanks!
As ajax is simply a request for data you cannot create a reliable loading bar easily.
However if you are doing loads of requests as you suggest in your question, "Which by the way is not the best idea".
You could do something like the code below. Again its pretty basic but will give your user a rough idea. I stuck it in a fidddle here for you http://jsfiddle.net/6dgAF/ its a basic example but should give you a jump off point.
function Status(data)
{
this.data = data;
this.size = this.data.length;
this.current = 0;
this.bar = $("#bar");
//Get width of each step of load
this.step = (this.bar.width() / this.size) ;
for(var i =0; i < this.size; i++){
this.getData(this.data[i]);
}
}
Status.prototype.getData = function(string){
//run your ajax here on each string and on success do this
//$.get( "ajax/test.html", function( string ) {
//this.current++;
//this.updateBar();
//});
this.current++;
this.updateBar();
}
Status.prototype.updateBar = function(){
//updates the bar with the current count * step width;
$("span",this.bar).width(this.step*this.current);
}
//Init object and put in dummy data
var status = new Status(new Array("string1","string2","string3","string4","string5","string6","string7","string8","string9","string10"));
An AJAX request is nothing else than requesting data from your server, just like any HTML page. The only difference is that you use Javascript, and don't feed the data to your browser as an HTML page, but use the data some way on your page.
One possible way to do the thing you want is the following:
Set an interval with the refresh rate, which calls a function getData
In getData you perform an AJAX request, which requests a piece of data from the server, which represents the current state. You might want to make sure the server only returns incremental updates, to avoid sending large amounts of data
Use the data on your front page, by displaying it in a friendly way to the user.
The main thing to keep in mind is that the server must save it's current state (the data which it has gathered with its queries), which it must return in the event of an AJAX request.
What you want is called XHR2 - personally I am using dojo
(dojo/request/xhr here)
However it should be possible with jQuery as well, search for jQuery XHR2 progress ...

Simple way to get multiple related objects in Parse.com with Javascript?

I have a Player class. Players can have x number of Trophies. I have the Player objectId and need to get a list of all of their Trophies.
In the Parse.com data browser, the Player object has a column labeled:
trophies Relation<Trophy>
(view Relations)
This seems like it should be so simple but I'm having issues with it.
I have the ParseObject 'player' in memory:
var query = new Parse.Query("Trophy");
query.equalTo("trophies", player);
query.find({
/throws an error- find field has invalid type array.
I've also tried relational Queries:
var relation = new Parse.Relation(player, "trophies");
relation.query().find({
//also throws an error- something about a Substring being required.
This has to be a completely common task, but I can't figure out the proper way to do this.
Anyone know how to do this in Javscript CloudCode?
Many thanks!
EDIT--
I can do relational queries on the user fine:
var user = Parse.User.current();
var relation = user.relation("trophies");
relation.query().find({
I don't understand why this very same bit of code breaks if I'm using a non-user object.
I finally sorted this out, though there is a caveat that makes this work differently than the documentation would indicate.
//Assuming we have 'player', an object of Class 'Player'.
var r = player.relation("trophies");
r.query().find({
success: function(trophies){
response.success(trophies); //list of trophies pointed to by that player's "trophies" column.
},
error: function(error){
response.error(error);
}
})
The caveat: You must have a 'full' player object in memory for this to work. You can't save a player object, grab the object from the success callback and have this work. Some reason, the object that is returned in the success handler is appears to be an incomplete Parse.Object, and is missing some of the methods required to do this.
Another stumbling block about the Parse.com Javascript SDK- A query that finds nothing is still considered successful. So every time you query for something, you must check the length of the response for greater than 0, because the successful query could have returned nothing.
This is what worked for me:
var Comment = Parse.Object.extend("Comment");
var commentsQuery = new Parse.Query(Comment);
commentsQuery.equalTo("parent", video);//for the given 'video' instance, find its children (comments)
commentsQuery.descending("createdAt");
return commentsQuery.find();
Note: of course, video is an instance of the Video class. And returning find() means I'll have to handle the 'promise' in whatever function calls this one.
And here is another function coming from the other angle:
getRecentCommentsOfAllVideos: function(limit) {
var Comment = Parse.Object.extend("Comment");
var commentsQuery = new Parse.Query(Comment);
commentsQuery.descending("createdAt");
commentsQuery.limit(limit);
commentsQuery.include("parent");//this enables the details of the comment's associated video to be available in the result
return commentsQuery.find();
}
(Be sure to read https://parse.com/docs/js_guide and search for the line that says "Include the post data with each comment".)
I also looked at these materials; maybe they'll help you (though they weren't much help for me):
https://parse.com/questions/how-to-retrieve-parent-objects-with-their-children-in-one-call-javascript-api
http://blog.parse.com/2011/12/06/queries-for-relational-data/

Categories

Resources