Twitter API - If Rate limit exceeded - javascript

I am developing a Twitter web app for myself. I am retrieving the latest trending topics.
Here's how I'm doing it:
$.ajax({
url: 'http://api.twitter.com/1/trends/1.json',
dataType: 'jsonp',
success: function(data){
$.each(data[0].trends, function(i){
$('div#trending').hide().append("<p><a href='"+data[0].trends[i].url+"'>"+data[0].trends[i].name+"</a></p>").fadeIn(1000);
//Cache into LocalStorage
localStorage["trending"+i] = data[0].trends[i].name; //Name
localStorage["trendurl"+i] = data[0].trends[i].url;//URL
});
}
});
But sometimes while I am developing it, the rate limit is exceeded.
How can I detect if the rate limit has been exceeded?
I cannot seem to detect if this error is being shown:
{"error":"Rate limit exceeded. Clients may not make more than 150 requests per hour.","request":"\/1\/trends\/1.json"}
I have tried it by:
success: function(data){
if(data[0].error != 'undefined'){
//load localstorage cache
}
}
But that doesn't seem to work.
Please help.
Thanks :)

The Twitter API sends a HTTP 400 status code when you are rate limited, so check for that:
$.ajax({
// ...
statusCode: {
400: function() {
alert( 'rate limited.' );
}
}
});
Also note that your comparison is a bit wrong. data[0].error != 'undefined' will always yield true when the error text is not 'undefined'. So even when you are rate limited, the error text won’t be 'undefined' and as such succeed. What you probably want to check is this:
if ( !data[0].error ) { // data[0].error is not null
// ...
}

try something like $.ajax({..}).fail(function(){});
i.e.
$.ajax({..})
.done(function() { alert("success"); })
.fail(function() { alert("error"); })
.always(function() { alert("complete"); });
and let me know how this works now.
cheers,
/Marcin

If you're not making an OAuth call, you'll be rate limited to 150 calls per hour. But, there's a small work-around which has worked for me.
According to the Twitter page on Rate Limiting (http://dev.twitter.com/docs/rate-limiting), "Rate limits are applied to methods that request information with the HTTP GET command. Generally API methods that use HTTP POST to submit data to Twitter are not rate limited, however some methods are being rate limited now."
Since the default type of an AJAX call is 'GET', try explicitly changing your type to 'POST' like this:
$.ajax({
url: 'http://api.twitter.com/1/trends/1.json',
type: 'POST',
dataType: 'jsonp',
success: function(data){
$.each(data[0].trends, function(i){
$('div#trending').hide().append("<p><a href='"+data[0].trends[i].url+"'>"+data[0].trends[i].name+"</a></p>").fadeIn(1000);
//Cache into LocalStorage
localStorage["trending"+i] = data[0].trends[i].name; //Name
localStorage["trendurl"+i] = data[0].trends[i].url;//URL
});
}
});
Hope this helps!
James

Related

Getting 400 Bad Request when making JSONP request to Yahoo Finance API

I want to have an input field that would suggest stock tickers as the user types in letters, like you'd see on Yahoo or Google Finance. I can't just use JSON unless I enable CORS, in which case it works. Here's code that I cobbled together from various questions I found on Stack Overflow (here and here) while researching the problem I'm facing.
$("input#stocklookup").autocomplete({
source: function(request, response){
$.ajax({
url: 'http://d.yimg.com/autoc.finance.yahoo.com/autoc?query='+request.term+'&region=US&lang=en-US',
dataType: 'jsonp',
jsonpCallback: 'YAHOO.util.ScriptNodeDataSource.callbacks'
});
YAHOO = {
util: {
ScriptNodeDataSource: {
callbacks: function(data) {
console.log(data);
}
}
}
};
}
})
Searching for 'a', I will get a 400 error and the URL is listed as
http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=a&region=US&lang=en-US&callback=YAHOO.util.ScriptNodeDataSource.callbacks&_=1462660878200
I think the extra numbers at the end are what may be causing the 400, but I don't know why it's being appended to the URL. If you navigate to the URL above, the results show properly in your browser.
I also tried using this block of code after seeing this page in the learn jQuery docs, but I also get a 400 error using this.
.$ajax({
url: 'http://d.yimg.com/autoc.finance.yahoo.com/autoc?region=US&lang=en-US',
jsonp: 'callback',
dataType: 'jsonp',
data: {
q: request.term,
format: 'json'
},
success: function(response){
console.log(response);
}
})
Any help to get me in the right direction would be appreciated. Thanks.
Update
$.ajax({
url: 'http://d.yimg.com/autoc.finance.yahoo.com/autoc?query='+request.term+'&region=US&lang=en-US',
cache: true, //<--new
dataType: 'jsonp',
jsonpCallback: 'YAHOO.util.ScriptNodeDataSource.callbacks'
});
YAHOO = {
util: {
ScriptNodeDataSource: {
callbacks: function(data) {
console.log(data);
}
}
}
};
This works for some requests but not others, some still return a 400 status.
I fixed it!
Added this in to my HTML file.
<meta charset="UTF-8" name="referrer" content="no-referrer">
Just a heads up - I have a couple of projects (Java and JavaScript) which call this API. They usually work but occasionally fail with a 400 without any change to the code - then work a few hours/days later, again, without changing the code. I think if there is some problem with the server it may return this rather than a correct error in the 500 range (server error - It's me, not you)
Errors in the 400 range should be a message from the server along the lines of "it's you, not me - fix your request before you send it again" but I don't think this is the case with this API.
For example - one of my requests which worked, didn't work, did work and then didn't is:
http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20=%20%22USDGBP%22&env=store://datatables.org/alltableswithkeys
in a browser I get the same 400 error but the following XML....
<error xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:lang="en-US">
<description>
No definition found for Table yahoo.finance.xchange
</description>
</error>
In short - it may be them not you!

Inactive status error received - JQuery

I have an Ajax request that is sent over to a file to grab information and return JSON.
Here is my request example:
$.ajax({
url: "admin/actions/ifp_get_events.php",
type: "post",
dataType: "json",
data:
{
'elevation_name' : 'global',
'function' : 'elevation_restrictions_events',
'parent_id' : d.ifp_id
},
success: function(data){
......do stuff
},
error:function(){
alert("error occured, please try again.");
}
});
Now I've been developing using Google Chrome and it works perfect but when I go to try this in Firefox or IE I am getting the following error:
The alert of coarse is being triggered and I have a response text of:
responseText:"
{
"status":"error",
"message":"You have been logged out due to inactivity."
}
{"status":"found","code":1,"original_request":
{"elevation_name":"global","function":"elevation_restrictions_events","parent_id":"26"},"data_retrieved":[{"evt_for":"Game Room","evt_restriction":"","evt_select_ability":"hide","evt_active_ability":"disable"},{"evt_for":"Bedroom 5 w\/ Bath 5","evt_restriction":"Craftsman Entry, Kitchen","evt_select_ability":"show","evt_active_ability":"enable"}]}"
Note that once the error message was given the new status section is the correct response I needed. I am just uncertain as to why this is happening in Firefox and IE?
Suggestions, thoughts?
If you need any more information please ask me.
Browser sessions aren't shared across browsers. In your case, you were logged in Chrome and hence the code was working as expected.
However, when trying out with FF and IE, you weren't logged in and hence the output was different.
add this line :
beforeSend: function (xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
},
after your data.
Since the valid csrf token is not going its logging you out of the site.

jQuery and Ajax - cannot POST

I am trying to login to a website using a known username and password and to get some data displayed from the site for a specific user account on that website. I am using jQuery and Ajax for this purpose. This is my code:
$.ajax({
async: false,
cache: false,
type: 'POST',
dataType: 'json', // json...just for example sake
data: ({
'login_username': username,
'secretkey': password
}),
url: 'https://mail.someserver.com/src/redirect.php',
success: function (data) {
alert("SUCCESS!")
if (data === '1') { // server returns a "1" for success
// success!
// do whatever you need to do
} else {
// fail!
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
// something went wrong with the request
alert("Failed!");
}
});
I've already made my search around the web and I know that browsers do not permit cross server ajax calls to prevent security issues, but I've already tried to use "jsonp" as dataType to no avail :(
So, what am I doing wrong?
Be sure that your url is not breaking the same origin policy -- that is, the request coming from the client cannot request data from a server from a different domain (there are exceptions to this rule, namingly CORS, but that requires that you make changes to the server/application you're talking to).
The solution to your problem would be to make the request from some server-side script, then in turn having your client application query that script, based on the same machine that's serving the application to the web.
My fault isn't at the code above, my fault was that in my manifest file (I am building a Google Chrome extension) I didn't have set proper permissions (https://*).
Sorry for the frustration!

How can I check for live updates without using setInterval/timeout?

Building a social network, I'm trying to fetch live notifications. Currently, the site sends an AJAX request every few seconds using setInterval. It looks something like this:
setInterval ( function(){
url = base_dir+"/ajax/file.php";
data = "data=someData";
$.ajax({
type: "POST",
url: url,
data: data,
dataType: "json",
beforeSend: function(x) {
if(x && x.overrideMimeType) {
x.overrideMimeType("application/json;charset=UTF-8");
}
},
success: function(JSON){
// retrieve data here
}
});
}, 5000);
That works perfectly, but I'm very worried about that creating servers overload. I tried the comet technique but for some reason it sends much more requests than the above code.
Is there any other more useful technique for pushing this data live?
EDIT:
For implementing long polling I used the following (used the example mentioned here: http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery):
(function poll(){
url = base_dir+"/ajax/file.php";
data = "data=someData";
$.ajax({
type: "POST",
url: url,
data: data,
dataType: "json",
beforeSend: function(x) {
if(x && x.overrideMimeType) {
x.overrideMimeType("application/json;charset=UTF-8");
}
},
success: function(JSON){
// retrieve data here
},
complete: poll,
timeout: 5000
});
})();
There's a possibility that I might not get the comet principle right.
PHP code:
// Checks for new notifications, and updates the title and notifications bar if there are any
private static function NotificationsCounter (){
//self::$it_user_id = query that retrieves my id for further checks;
//$friend_requests_count = query that retrieves the friend requests count;
//$updates_count = query that retrieves the updates count;
$total_notifications = $friend_requests_count+$updates_count;
if ($total_notifications > 0) $addToTitle = "(".$total_notifications.")";
else $addToTitle = "";
if ($updates_count > 0) $counterHTML = "<span class='notification_counter' id='updates_counter' style='float: right;'>".$updates_count."</span>";
else $counterHTML = "";
$data = array("counter"=>$total_notifications,"addToTitle"=>$addToTitle,"counterHTML"=>$counterHTML,);
echo json_encode($data); // parse to json and print
}
Since Facebook uses PHP as well, how do they do it?
You should use websockets. You can connect to the server and register onmessage handler. Whenever the server has anything to be send to client, your handler will get invoked. No timeout needed.
Check for websocket support in your browser. As of now, only Chrome, Opera and Safari support them.
if ('WebSocket' in window){
/* WebSocket is supported. You can proceed with your code*/
} else {
/*WebSockets are not supported. Try a fallback method like long-polling etc*/
}
Connecting
var connection = new WebSocket('ws://example.org:12345/myapp');
Handlers
connection.onopen = function(){
console.log('Connection open!');
}
connection.onclose = function(){
console.log('Connection closed');
}
connection.onmessage = function(e){
var server_message = e.data;
console.log(server_message);
}
Documentation: http://www.developerfusion.com/article/143158/an-introduction-to-websockets/
Websockets will be the way to go once they are more universally implemented across the major browsers - I would guess a minimum of 5 years.
The last I heard Facebook chat uses comet and a whole bunch of servers. If you want something more lightweight I can think of two options.
Reduce the polling interval. This is strictly a UI issue - users may have a perfectly acceptable experience with intervals as long as a couple minutes. The only way to know for certain is through user testing, but polling every 5 seconds is probably overkill. No matter what you choose as the optimal interval, this does give you an quick way to scale if you are getting hammered - just crank up the interval until the servers stop melting.
Use HTTP validation caching. You can make the requests more lightweight if the server only returns a response body when the content has changed since the last request. You will have to build something custom using ETag or Last-Modified headers and a lightweight modification checking system on the server, but it might save you a few bytes.

How to know if url is available?

I have a link redirecting to an intranet direction:
Go
Only users in intranet can access, otherwise they get a 404 error. I want to know if the the url is valid before redirecting, this way users out of intranet won't get the 404 error but a message saying 'You don't have access'. How can I do this with jquery or javascript?.
EDIT:
Well, thank you very much, but unfortunately any method does not work for me. Sorry, I didn't mention that website and intranet url are in differente domain.
Finally I had to validate user IP in codebehind and write or not the intranet url.
You could make an ajax request first, something like:
$.ajax({
url: "http://10.2.68/name/",
context: document.body,
success: function(){
window.location = "http://10.2.68/name/";
}
});
That could be run by binding to the click event on the link.
Not sure if it will work due to cross origin stuff, but might be a good place to start.
You can use this jQuery plugin to make a head request to the remote file, if it comes back with something it is good (and you can display it for instance) otherwise don't show it
Plugin:
http://binarykitten.me.uk/dev/jq-plugins/88-jquery-plugin-ajax-head-request.html
Perhaps use an htaccess file to detect the internal network instead?
The best answer would be to disable the link if it's inactive, before the user tries to click it (why make them try?).
jQuery(function($) { // make sure dom is ready
$.ajax( {
url: url,
//dataType: 'JSONP', //might need this?
complete: function(xhr) { // use complete so it fires on error OR success
if( xhr.status == 200 || xhr.status == 304 ) {
$('#link').addClass('valid');
}
else {
$('#link').addClass('invalid').click(function() { return false; });
}
}
});
});
But if you don't want the call because there are going to be thousands of users looking at the page every minute...
jQuery(function($) { // make sure dom is ready
$('#link').click(function() {
$.ajax( {
url: url,
//dataType: 'JSONP', //might need this?
success: function() {
window.location = url;
},
error: function() {
// does this work with JSONP? be sure to check!
window.alert('could not connect');
}
}
});
});
Assuming your anchor has an ID:
<a id="lnkGo" href="http://10.2.68/name/">Go</a>
And your jQuery code might look like this:
$("#lnkGo").bind("click", function() {
var $that = $(this);
$.ajax({
url: $that.attr("href"),
statusCode: {
200: function() {
window.location = $that.attr("href")
},
404: function () {
alert("Sorry, page is unavailable...");
}
}
});
return false;
});
Also, please keep mind that this won't work on cross-domain issue. The url has to be same as the current domain.

Categories