im trying to make a simple notification system using Ajax and Jquery.
What i've done so far is:
Created a php file from which i load latest post and its title
Return json from php file mentioned above containing latest post and it's title
Created ajax post request that fetches the latest post from the json and its name using the data parameter in success: function(data)
Set an interval that repeats ajax call every 5 seconds
prepend the latest post title in notification div
Problems i have are:
If i set the interval on 1 minute and create 2 or more new posts it will only give the newer one (obviously since i called ->first() from my ->latest(), otherwise it wont load anything)
As i mentioned before, my setInterval is set to 5 seconds, and then it loads the latest post, and it does that every 5 seconds so i have an identical new post every 5 seconds until the newer one comes, i tried fixing it by prepending only higher id than the last one, but im not sure how reliable is that
Scripts:
Notification.php:
$post = Post::latest()->first();
$post_title = $post->title;
return response->json(array('post' => $post, 'post_title' => $post));
View with AJAX:
function getnewnotif()
{
$.ajax({
type:'POST',
url: url_to_notification.php,
success: function(data){
$('#notif').prepend(data.post_title);
}
});
}
setInterval(getnewnotif(), 5000);
You were definitely on the right track with IDs, but more reliable is likely the creation (or updated) date.
In its simplest form, when you send your request for more posts, send a "last request date" parameter. On the server, use that to only grab posts that have been created (or modified - not sure which you want) after that date. On the client, where you make the ajax calls, you'll need to remember the last date you requested data from the server, so you can use it in your next ajax call.
But that will not work perfectly well when multiple timezones are involved.
A sturdier approach is for the server to tell you it's local time. So you send your first ajax call, and along with the list of posts, the server also returns the time it sent you the data. Your javascript grabs that date, and on your next ajax call, you send that to the server. It can then return to you just new posts that were created after that date. Since it's always server date vs server date, timezones don't matter here.
Hope this helps!
Related
How can I get the value of a cookie in oracle from a request that was originated with ajax from a non-apex page (inside an apex server)?
I wanted to start by creating a function that returns the value of the login cookie and use that function to return the value to the browser to see that it can be done.
So I created a resource template and handler with the following source: select test() from dual.
The test function is declared as:
create or replace function test return varchar2
is
c owa_cookie.cookie;
begin
c := owa_cookie.get('LOGIN_USERNAME_COOKIE');
return c.vals(1);
end;
When I run select test() from dual from an sql commands window I get the value of the cookie, but when I send a request to the handler with ajax I get the following error:
An error occurred when evaluating the SQL statement associated with this resource. SQL Error Code 6502, Error Message: ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "SYS.OWA_UTIL", line 354
ORA-06512: at "SYS.OWA_COOKIE", line 59
ORA-06512: at "SYS.OWA_COOKIE", line 179
ORA-06512: at "<no need to see this>.TEST", line 5
I've been using the following call (checking the result through the network dev tools)
$.ajax({url: "<handler url here>"})
Update:
The reason I'm using a rest service is because the page that originates the request is not an apex application but it is on the same domain (so it has the same cookies).
This is what I think is happening: The cookie is sent as part of the http request header of your apex application call. The rest call is another http request, unrelated to your apex http request and I don’t believe the header of that request includes the cookie. So in the database session that is created as part of your rest request the cookie will not exist. You could probably set the header of the rest request yourself to fix this.
--UPDATE--
To check which cookies can be read, create a rest handler of source type pl/sql with the following source:
DECLARE
l_names owa_cookie.vc_arr;
l_vals owa_cookie.vc_arr;
l_num_vals INTEGER;
BEGIN
owa_cookie.get_all(
names => l_names,
vals => l_vals,
num_vals => l_num_vals);
APEX_JSON.open_array('cookies');
FOR r IN 1 .. l_names.COUNT LOOP
APEX_JSON.open_object; -- {
APEX_JSON.write('name', l_names(r));
APEX_JSON.write('value', l_vals(r));
APEX_JSON.close_object; -- } cookie
END LOOP;
APEX_JSON.close_array; -- ] cookies
END;
The apex username cookie is not in that list of cookies. I suggest you create your own custom cookie in an after-login process in apex.
I verified that a cookie set with the following code in an apex process is picked up by the rest handler (based on blog https://www.apex-at-work.com/2012/05/apex-simple-cookie-example.html)
begin
owa_util.mime_header('text/html', FALSE);
owa_cookie.send(
name => 'CUSTOM_USER_COOKIE',
value => :APP_USER,
expires => sysdate + 30 );
apex_util.redirect_url (
p_url => 'f?p=&APP_ID.:1:' || :SESSION,
p_reset_htp_buffer => false );
end;
To get a cookie from an AJAX request within APEX, you can use the OWA_COOKIE package, but you do not need to define any templates or handlers. It can all be done from within the page (or calling an external procedure from within the page). Below are the steps I used to get the JSESSIONID cookie.
I have built an example application on apex.oracle.com that you can check out.
Page Setup
The page is very simple with just one text box and one button. The button's action is set to Redirect to URL and this is the target:
javascript: apex.server.process("AJAX_TEST", { }, { success: function (pData) { console.log(pData); apex.item("P10_JSESSIONID").setValue(pData); }, dataType: "text", error: function (jqXHR, textStatus, errorThrown) { } }).always(function () { });
The javascript is calling the AJAX Callback (which is shown below) and storing the output in the P10_JSESSIONID page item as well as logging it to the browser console.
AJAX Callback Setup
The code in the AJAX Callback is very similar to the code you shared. I am getting the cookie then printing it out with HTP.P. This is all that is needed to return the value of the cookie to the page to be used for whatever you'd like. You can also make the code in the AJAX callback call a standalone procedure compiled into the database if you so choose.
Update
I updated my example application so that there will be a dropdown showing all of the cookies, then you can select from the list and click the button to send an AJAX request to get the value of that cookie.
I'm using a simple jQuery AJAX function that runs extremely slow (10-15 seconds) the first time it's called, and then runs normally at <1 - 2 seconds each time it's called after that first time. I cannot figure out why this is happening but need to speed it up as much as possible. Here is the function:
function getNewItemAlt(apiUrl, callType, apiKey, dataType, returnValue, appendToWrapper) {
// ajax call to the api
return $.ajax({
type: callType,
url: apiUrl,
data: apiKey,
dataType: dataType,
success: function(result) {
appendToWrapper.closest('.game_play_area').find('.game_loader').remove();
// this is the thing that we want (probably either
// an image url or an actual value)
var desiredReturn = deepValue(result, returnValue);
var specialClass = '';
console.log(typeof desiredReturn)
if (typeof desiredReturn === 'number') {
specialClass = 'number'
}
// if it's a URL then it's an image and can be setup
// in an imgage tag and added to the dom
if (desiredReturn.toString().substring(0, 4) == "http") {
$(appendToWrapper).children('.game_image').remove();
$(appendToWrapper).prepend('<img class="game_image" src="' + desiredReturn + '" />');
} else {
$(appendToWrapper).children('.game_value_return').remove();
$(appendToWrapper).prepend('<p class="game_value_return ' + specialClass + '">' + desiredReturn + '</p>');
}
// clear the space to play the game
// $(currentGameWrapper).children('.game_intro').remove();
// show the game
// currentGameWrapper.children('.game_play_area').removeClass('hide');
},
error: function(err) {
console.log(err);
}
});
}
An example of an API that I'm making a request to is the Giphy API. I'm not convinced this is a server issue because it happens only on the first call to the api and then the subsequent calls are speedy.
Any ideas why this is happening and what can be done to make this run faster?
Considering the whole issue Javascript (client side) + API (server side) could complicate diagnosing the issue, so my suggestion to get a more specific answer would be to isolate the issue first.
Answering your general question, Reasons why?: It could be a lot of things but the remarkable ones are:
Handshake: the first interaction between your page and the server makes the remote server to authenticate you and validate your session. Later calls wont go through that process.
Server first execution: (less probable if you are using public APIs) if you are using a remote server with Java for example, that you are restarting, the first time you call a service it will load the instances, but for future calls those instances are already created hence they respond faster.
Network: (I don't think so... but...) trace your HTTP request to see how many jumps it has and how much is taking for them to be resolved.
How to Diagnose (isolation): Measure the time each step takes, it could be a simple print of your current time. I would break it the in the following steps:
Preparing the call to the API.
Calling the API.
Getting the data.
Manipulate the received data on the client side.
NOTE: steps 2 and 3 could go together.
How to mitigate this from happening (it doesn't solve the issue, but mitigates it):
Handshake: if the issue is related with authentication/authorization I recommend you to do an empty pre-fetch (without requesting any data) to deal with the handshake. Then you do a data fetch when you need it without that overhead.
Server first execution: you don't have too much to do here unless you own the server also. In this case I recommend also a pre-fetch but calling the entire service to initialize the server objects.
Javascript API: if the problem is dealing with the data on your client side then review how to optimize your Javascript code.
This might be a long shot. "appendToWrapper" is an object passed in by reference. If it's taking a long time to resolve (ie it takes 10 seconds or so to find ".game_play_area" etc... in the DOM) then it would be slow the first time, but saved in the calling function and fast subsequent times.
It might be easy to check. If you could make a deep copy of the object before passing it in, we would expect the AJAX to be slow every time, not just the first time. If that's the case, you'd need to clean up your selectors to make them faster. Perhaps use ids instead of classes.
I am writing an application that allows a user to dynamically select which columns they want to pull from our database (all public internal data) as well as customize their logic (WHERE Clause).
The result sets from these queries can be anything from a 10 records to our whole table of over 35,000 records.
On load of the result page, I trigger an AJAX function which runs the query that user has chosen and this triggers to stored procedure to run the query. This data is then passed to the AJAX success function and rendered to the DOM so it can be manipulated, exported etc.
--
The Issue:
When people choose to download the entire table (not often but certain departments have a need), we are having timeout issues which can be expected.
I am trying to find out where the bottle neck is to try and improve the experience.
When I run the query directly on the database for the 35,000 record result set, it takes about 12 seconds over VPN so I don't think the issue is with the database it self.
You can see in the image above where the timeout happened on the POST call.
I am trying to understand how the process flows for fetching / writing data to the DOM. Is the connection that is fetching the data from the database timing out or do we successfully have that data but we are timing out trying to write the 35,000 table rows?
Example Code:
var output = '';
$.ajax({
url: "api/fetchDashboardRender",
type: 'POST',
cache: false,
data: {
dashboardID: dashboardID
},
error: function(err) {
alert(err.statusText);
},
success: function(data) {
// Example .. Loop over the data in the result set
$(data).each(function(){
// Append each table row to a variable
output += '';
});
// Once done, append the variable to the DOM
$('#results').append(output);
}
});
Questions:
While I understand there is no need to write that much data to the DOM, there are reasons they want it done and I am following instruction.
Does the success function of an AJAX call include the DOM
manipulation or is it it successful once the data has been retrieved
from the source?
Is there a better way to approach this type of situation outside of making multiple calls in a paginated approach for batches of data?
Can you help me identify the main bottle neck here as to where things are being hung up?
Thanks for any pointers.
Let's say we have a grid, and the data comes from the server Meteor.call(). When user clicks on the pagination, or changes sorting or filtering options, some animation is shown, and the method is called. Once data comes back, we hide the animation and render the list. This works great, but we would also like to abort current call if the user changes their mind before data comes back and goes to another page, or changes another filter. Is there a way to do that? In AngularJS I used .abort() on ajax http requests, and that worked perfectly... is Meteor lacking a similar function?
You can use beforeSend option for that:
var requestObject;
HTTP.call("GET", url, {
beforeSend: req => requestObject = req
}, (error, result) => {
// do your stuff ...
});
requestObject.abort();
Note: at the time of writing this is only supported on client.
i am trying to display the data fetched from database in the loop and between loop i call the function and send ajax request its not working.Actually its displays the only if i used alert command. If i used alert then the browser display the div and then alert if i clicked ok then it displays the second div then again show alert.
Here is the js code
function like(divid,id,session) {
var orgnldiv=document.getElementById(divid);
var ndiv=document.createElement('DIV');
var idd=id+5000;
ndiv.id =idd;
ndiv.className="likeclass";
orgnldiv.appendChild(ndiv);
var dynamicdiv=document.getElementById(idd);
var span=document.createElement('span');
var spanid=idd+5000;
span.id=spanid;
span.className="spanclass";
dynamicdiv.appendChild(span);
var xmllhttp15;
if (window.XMLHttpRequest) {
xmlhttp15=new XMLHttpRequest();
} else {
xmlhttp15=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp15.onreadystatechange = function() {
if (xmlhttp15.readyState==4 && xmlhttp15.status==200) {
document.getElementById(spanid).innerHTML=xmlhttp15.responseText;
}
}
xmlhttp15.open("GET","spancount.php?postid="+id+"&userid="+session);
xmlhttp15.send();
// alert(spanid);
}
please suggest me what can be the reason of this problem my code is working well only if i use alert
The reason why your code works when you use alert is because whenever the alert function is called. The program flow is paused. In other words, your loop wont continue to make another Ajax call until you dismiss the alert.As a result, the request gets handled properly and the response data appears in the span div. that is why I had mentioned to make your calls synchronous instead.
So to answer the question you asked in the comment, Yes at times too many Ajax calls can be a problem. Let's say that the loops runs more than 15-20 times, that means 15-20 simultaneous requests. Now, think about the number of times the same request is being handled by the php script? Definitely a problem here!
Even with Jquery Ajax, the chances of the loop completing successfully is also 50-50 actually because it all boils down to the amount of requests being made , the bandwidth being used and how the request is being processed at the server.
One possible way to fix this problem is : Rather than constantly requesting small peices of data again and again from the server in the loop, Make one Ajax call and get the entire data as json. Then, parse the json and append data to the spans by using the particular span id to extract the relevant data from the json object.
You might have to do a little bit of tweaking in both the above javascript and spancount.php . But it will definitely Save you A LOT of bandwidth. You gotta consider the fact that more than one person could be using your site!!
Hope that cleared up things, all the best with your project :D