I have a website, where users can get inbox messages and notifications while they are on the website. (Like on facebook, you see (1) at the begining of the tile as you have notification)
Currently I have an ajax request which grabs the data the title has to show. It works liek charm but the issue is that this file is called every 10 seconds. If user has 10 page tabs though, this file is called 10x10=100 times.. if my site has thousand users, you understand how much load it would generate.
I though of running the javascript on active tab only but how can I update the title of all opened tabs of my website? Any other suggestion?
Here is my code
var oldtitle=$(document).attr("title");
var checker=function(){
$.ajax({
url : 'live_title.php',
type : 'POST',
success : function(data) {
... code ....
... code ....
... code ....
if (sum>0) {
$(document).attr("title", "("+sum+") "+oldtitle);
}
}
});
}
setInterval(checker,20000);
checker();
A cache mechanism seems the right way to go.
First idea: use HTTP caching
Be sure to add a parameter as a query string with the current timestamp rounded to the previous 10th of second.
Be sure your web server sends the correct header for the HTTP cache to work. It's best with a GET request.
Example:
$.ajax({
url : 'live_title.php',
type : 'GET',
success : function(data) {
// code
},
data: {t: Math.floor((+new Date())/10000)}
}
// we send a request similar to live_title.php?t=142608488
Second idea: use window.localStorage as a secondary local cache.
Additionnaly to the first idea:
var getCache = function(t) {
if (window.localStorage) {
var liveTitle = localStorage.getItem('liveTitle') || {};
return liveTitle[t] || null;
}
};
var setCache = function(t, data) {
if (window.localStorage) {
window.localStorage.setItem('liveTitle', {t:data});
}
}
var run = function() {
var t = Math.floor((+new Date())/10000);
var cache = getCache(t);
var success = function(data) {
/*code*/
};
if (cache) {
success(cache);
}
else {
$.ajax({
url : 'live_title.php',
type : 'GET',
success : function(data) {
setCache(t, data);
success(data);
},
data: {t: t}
}
}
}
I don't think you can do what you want easily.
Moreover to optimize that, I would recommend to use cache :
One time a tab calls the method which count the messages, do the query and cache the result to a simple file or in memory
during the next 5 minutes, each time a tab calls the method, use the cache and do not query the database
when the 5 minutes are passed, do again a query, cache it and so on.
Like this, on 100 calls, you have only 1 big request, others are like requesting a js or img files
Related
I'm making a function to get a xml file and edit it. I've never done that before so I searched a good way to get an xml file. I decided to use ajax, but the file is never returned because the url is undefined.
EDIT :
I edited the code and made the treatment in the success function. Now there is no problem with this file.
Here is the update of the ajax part :
$.ajax({
type: 'GET',
url: 'allrtp.xml',
dataType: 'xml',
success: function(xml) {
//file = $.parseXML(xml);
// Editing the file to have the good dates
$(xml).find('StartDateTime').text(start);
$(xml).find('EndDateTime').text(end);
var strFile;
if (window.ActiveXObject) {
strFile = xml.xml;
} else {
strFile = (new XMLSerializer()).serializeToString(xml);
}
var encoded64 = Base64.encode(strFile); // Encoded in base64
var encodeURL = encodeURIComponent(encoded64); // Encoded URL
var AR = urlAR + encodeURL; // The URL to open
window.open(AR, '_blank');
}
})
Now all is working well about the xml file, I have a little problem with the window.open, which open my url but with %31 at the beggining, but it's another problem.
Thank you for your help !
file is undefined because you are declaring it inside a ajax success function
function openRecords(start, end) {
// Extraction of the xml file
var file;
$.ajax({
type: 'GET',
url: 'allrtp.xml',
dataType: 'xml',
success: function(xml) {
file = $.parseXML(xml);
},
error: function(ex) {
console.log(ex);
}
})
// Test
var start = '2016-02-15T12:57:00+01:00';
var end = '2019-02-16T13:57:00+01:00';
setTimeout(function(){
// Editing the file to have the good dates
file.find('StartDateTime').text(start);
file.find('EndDateTime').text(end);},1500);
}
Add an error callback:
error: function (ex) {}
Many things can be happening, you will get more info with the error callback. Probably you are querying an incorrect url. Do not trust that undefined upon url, see what returns your jquery ajax function. Maybe you should be querying something like '\files\xxx.xml'.
can you give me a picture of Network in your broswer? I want to know the URL is send or not:
1. F12 open your console
2. select the Network tab
3. refresh the broswer
4. check the request is send or not
I spend about 2 hrs looking to do a batch call using Appcelerator Module.Facebook. I needed to get the Profile name and Picture. And I thought I wanted to do this in one HTTP request instead of two.
After a deep dive i finally found a way to do. I will post my answer in the answer section below.
Incase anyone else comes up against this..
var fb = require('facebook');
var log = require("log");
...
// After logging in
// gets user profile image and name uses a batch method example
function getUserInfo(userId) {
var batch = 'batch=[{"method":"GET", "relative_url":"me"},{"method":"GET", "relative_url":"me/picture"}]&access_token=' + fb.getAccessToken();
var url = "https://graph.facebook.com?" + batch;
var client = Ti.Network.createHTTPClient({
// function called when the response data is available
onload : function(e) {
log.args(this.responseText);
},
// function called when an error occurs, including a timeout
onerror : function(e) {
log.args(e.error);
},
timeout : 5000 // in milliseconds
});
// Prepare the connection.
client.open("POST", url);
// Send the request.
client.send();
}
This is how you would do a batch call using AppC, however there is a better way to get the info that i needed. In my case I only needed the Facebook name and picture
function getGraphPath(userId) {
fb.requestWithGraphPath('me?fields=id,name,picture', {}, 'GET', function(e) {
if (e.success) {
log.args('Modules.Facebook.requestWithGraphPath', JSON.parse(e.result));
} else if (e.error) {
log.args(e.error);
} else {
log.args('Unknown response');
}
});
}
I am struggling with this issue for 2 days...
I have a JavaScript array (20,000K rows and 41 columns). It was originally received in javaScript through an ajax call as shown below,
var dataArray = [];
var dataRequest = {};
dataRequest.SearchCondition = 'some value';
$.ajax({
type: "POST",
url: "api/GetData/ProcessRequest",
dataType: 'json',
cache: false,
async: true,
crossDomain: false,
data: dataRequest ,
success: function (response) {
dataArray = response;
},
error: function (xhr, textStatus, errorThrown) {
dataArray = null;
}
});
In the application, the user will verify the data and send it back to Web API method.
I am trying to send the same data back (dataArray) to web api method but, it fails. Please see the code below,
Option 1: (failed - the request did not hit web api method)
var dataArrayJsonStr = JSON.stringify(dataArray);
$.ajax({
type: "POST",
url: "api/SendData/ProcessRequest",
dataType: 'json',
data: {'dataValue':dataArrayJsonStr },
success: function (response) {
alert('success');
},
error: function (xhr, textStatus, errorThrown) {
alert(errorThrown)
}
});
In IE 8, I am getting 'out of memory' exception popup. (most of our application users still have IE 8)
In Chrome, it crashes.
Option 2 tried: (don't know how to read the value)
I tried to send the same value to web api through XmllHttpRequest
var dataArrayJsonStr = JSON.stringify(dataArr);
var xmlRequest;
if (window.XMLHttpRequest) {
xmlRequest = new XMLHttpRequest();
}
xmlRequest.open("POST", "api/SendData/ProcessRequest", false);
xmlRequest.setRequestHeader('Content-Type', 'application/text');
xmlRequest.send("dataValue=" + dataArrayJsonStr);
Using Chrome, I am able to post the data successfully to Web API, I am seeing the content-length as '128180309'. But, I don't see the values. How do i get the values in Web API?
Please suggest me how to send large data back to web api from javascript.
Thanks,
Vim
I think you create overhead, maybe I wrong, you can edit me.
Did you really need send back all datas back or you just need send modified data?
Because in real life hard to imagine that user will review 20.000 of rows.
Good example is ExtJS stores, you can see example here
Key thing of stores that they send back to the server only modified or deleted data, it save browser, network and server resources.
Try to add more memory for API or more time excecution, also you can try return data in more small parts. Defining the number of parts to send.
Did you try to send the data by chunks?
I mean, you need to split it in small pieces and perform multiple number of requests.
For example, it can be like:
--HELLO SERVER. STARTING TRANSMITION FOR DATA SET #177151--
PIECE 1/13
PIECE 2/13
...
PIECE 13/13
--BUE SERVER--
So, it will take some time, but you can send any amounts of data without memory problems. If you're struggling with it for 2 days, I think you got some time to code it :)
UPD1: Client code example.
Here's an example of client code. This is a simple chunking algorithm.
Have to say I didn't test it, because it would take a lot of time to represent your situation.
So, you should read it and get the point.
You have a simple function, that takes you whole data set and callbacks for each response (to update your progress bar, e.g.), for successful finish and for error.
Hope, it will help you to make some problems.
Also, I can help you to build architecture on the server-side, but I need to know what technologies do you use.
function sendData(data, onEach, onFinish, onError) {
var CHUNK_SIZE = 1000;
var isFailed = false;
var chunkNum = 0;
var chunk, chunkStart, chunkEnd;
while(data.length + CHUNK_SIZE > chunkNum * CHUNK_SIZE) {
if(isFailed) {
return;
}
chunkStart = chunkNum * CHUNK_SIZE;
chunkEnd = chunkStart + CHUNK_SIZE + 1;
chunk = {
num: chunkNum,
data: data.slice(chunkStart, chunkEnd)
};
ajaxCall(chunk);
chunkNum++;
}
function ajaxCall(data) {
$.ajax({
type: "POST",
url: "api/GetData/ProcessRequest",
dataType: 'json',
async: true,
data: dataRequest ,
success: function (response) {
onEach(data, response);
},
error: function (xhr, textStatus, errorThrown) {
isFailed = true;
onError(arguments);
}
});
}
}
I am trying to implement a progressbar when a user executes find request in my web application(php/js/html).
When the user executes the find request, application executes php script using ajax, this script periodically stores its progress in session variable.
What I tried to do is to poll the server with another ajax request to ask for the session progress variable, but the variable does not exist.
Why is this happening, is this not possible using php sessions?
Thanks
JS logic:
// When the user selects interested object, find it on the server
$(document).on('change', '#findStreamer', function()
{
$streamerId = $(this).val();
$streamerName = $('#findStreamer option[value="'+$streamerId+'"]').text();
console.log('findDB', $streamerId, $streamerName);
addProgressBar();
getProgress();
$.ajax({
type: 'POST',
url: 'serverlink/findobject',
data: {
findChannel: $streamerName,
checkOnline: true
},
success: function(response)
{
$streamData = JSON.parse(response);
$('#streamPreview').remove();
// $('#findPanelToolbar').before($streamData.streamerView);
console.log($streamData);
}
});
});
function getProgress()
{
$.ajax({
type: 'POST',
url: 'serverlink/getprogress',
complete: getProgress,
timeout: 60000,
success: function(response)
{
$progresValue = response;
updateProgressBar($progresValue);
}
});
}
Server logic:
public function action_findobject()
{
$_SESSION['percentage'] = 0;
if(!(Input::is_ajax()))
{
$response = Response::forge();
$response->set_status(400);
return $response;
}
// Long actions //
$_SESSION['percentage'] = 10;
// Long actions //
$_SESSION['percentage'] = 45;
// Long actions //
$_SESSION['percentage'] = 100;
return $Outputdata;
}
public function action_getprogress()
{
return $_SESSION['percentage'];
}
I think you need create php script, which will execute some tot big part of process and send json with %. Also percents need to be stored in session. In browser you will invoke ajax till get some error or result 100%. After you got answer from server, if percents<100 -> show new percent line to customer and do the same request to server..
Not a solution so I'll wikify this but to answer the question, "is this not possible using php sessions?"... looks like a no - or at least not in the code's current form. You would have to delegate the resource-intensive operation to another process somehow as the following simple test suggests that the first operation is blocking.
<?php // sleep.php
session_start();
$_SESSION['foo'] = gmdate('r');
sleep(10);
<?php // test.php
session_start();
echo !isset($_SESSION['foo'])
? 'session not set'
: $_SESSION['foo'];
Test:
Browse /sleep.php which sets some value in the session then waits for 10 seconds (arbitrary) to mimic some exhaustive program/execution. Open a new tab inside of the 10 second delay and browse /test.php.
Expected Result:
/test.php immediately returns the date that was set by /sleep.php
Actual Result:
/test.php request hung/waited until /sleep.php request had finished.
I managed to solve this problem using caching in a file, dont know how optimal that is, but thanks to everyone for your suggestions!
I have a WordPress plugin that I am working on that Polls all the major Social Networking sites and returns the social counts ( followers ) for a specific user.
This can be quite slow and intensive on the server so I have built the plugin using WordPress Transient Caching to store the details returned from the Social Network sites, and am also using jQuery AJAX json to display the data.
These are the main functions:
Retrieve the Facebook Count
/**
* Fetch Facebook count.
*
* #param string $url The url to fetch.
* #return int of Facebook counts.
*/
function ass_get_fb_likes($facebook_id) {
try {
$json = wp_remote_get("http://graph.facebook.com/".$facebook_id);
if(is_wp_error($json))
return false;
$fbData = json_decode($json['body'], true);
return format(intval($fbData['likes']));
} catch (Exception $e) {
return false;
}
}
this above function is also connected to another function that handles the Transient caching. This aspect works great.
Handles the initial display of the Social Network data
jQuery(function($) {
$('#fblikes').advanceddashboardwidget({
'action':'get_facebook_likes',
'service':'facebook',
'countof':'likes',
'callback':'formatCount'
});
});
Helper function to format the display
function formatCount(element,count){
var display_count='';
count=parseInt(count,10);
if(count>1000000)
{
count=count/1000000;
count=count.toFixed(0);
display_count=count+'m';
}
else if(count>1000)
{
count=count/1000;
count=count.toFixed(0);
display_count=count+'k';
}
else
{
display_count=count;
}
element.html(display_count);
}
The below function if the one giving me issues. It is used to communicate with WordPress to call the PHP functions and retrieve the data.
(function($) {
$(document).ready( function() {
var AdvancedDashboardWidget = function(element, options)
{
var ele = $(element);
var settings = $.extend({
action: '',
service: '',
countof: '',
query: '',
callback:''
}, options || {});
this.count=0;
var url='';
switch(settings.service)
{
case 'facebook':
if(settings.countof=='likes' || settings.countof=='talks')
{
ajaxCall(action,ele,settings);
}
break;
}
};
var ajaxCall = function(action,ele,settings){
opts = {
url: ajaxurl, // ajaxurl is defined by WordPress and points to /wp-admin/admin-ajax.php
type: 'POST',
async: true,
cache: false,
dataType: 'json',
data:{
action: settings.action // Tell WordPress how to handle this ajax request
},
success:function(response) {
//alert(response);
ele.html(response);
return;
},
error: function(xhr,textStatus,e) { // This can be expanded to provide more information
alert(e);
//alert('There was an error deleting the cache');
return;
}
};
$.ajax(opts);
};
$.fn.advanceddashboardwidget = function(options)
{
return this.each(function()
{
var element = $(this);
// Return early if this element already has a plugin instance
if (element.data('advanceddashboardwidget')) return;
// pass options to plugin constructor
var advanceddashboardwidget = new AdvancedDashboardWidget(this, options);
// Store plugin object in this element's data
element.data('advanceddashboardwidget', advanceddashboardwidget);
});
};
});
})(jQuery);
The Issues
The issue is that when the data is returned from the transient functions there is always an extra 0 ( zero ) appended to the number. From what I have been reading this could be because I am using "json" instead of "jsonp".
When I change it to "jsonp" I get an error "Error: jQuery172011280598581866697_1353705456268 was not called". I guess this has to do with the callback function.
So far I have found this the fastest way to display this information on a site. If the data exists in the transient cache the pages load quick but if not that can take a few seconds and that is where I want jQuery to come in and maybe display a loading graphic until the data is retrieved.
Any help would be greatly appreciated.
Before you return your AJAX data back to the AJAX function, you need to die(), otherwise it falls through to WordPress' which ends with die('0').
Edit:
WordPress now has (since 3.5.0) functions available for this:
wp_send_json_success( $data ): http://codex.wordpress.org/Function_Reference/wp_send_json_success
and wp_send_json_error( $data ): http://codex.wordpress.org/Function_Reference/wp_send_json_error.