How to store the ajax response in browser cache with jquery - javascript

I'm trying to store the ajax response in browser cache. I know to store it for only url like (example.com), but want to store the data which having url like (example.com?xyz=abc%20efg&mno=hjk).
My code :
beforeSend: function () {
var addC=url; // I want to add data also with this url
console.log(addC);
if (localCache.exist(addC)) {
printRes(localCache.get(url));
console.log("cached values");
return false;
}
return true;
},
And
var localCache = {
data: {},
remove: function (url) {
delete localCache.data[url];
},
exist: function (url) {
return localCache.data.hasOwnProperty(url) && localCache.data[url] !== null;
},
get: function (url) {
console.log('Getting in cache for url' + url);
return localCache.data[url];
},
set: function (url, cachedData, callback) {
localCache.remove(url);
localCache.data[url] = cachedData;
if ($.isFunction(callback)) callback(cachedData);
}
};
Please anyone help me to solve this.

By reading the docs from
MDN i Think you are doing wrong. If you want to cache ajax response CACHE property to true
in your ajax call ,also see to it that you provide proper cache expiration header from server.
Also
[from MDN]
Never access cached files by using traditional GET parameters (like other-cached-
page.html?parameterName=value). This will make the browser bypass the cache and attempt to get
it from network. To link to cached resources that have parameters parsed in JavaScript use
parameters in the hash part of the link, such as other-cached-page.html#whatever?parameterName=value.
if you are looking for local storage[key value storage]
globalStorage['cache_1'].setItem("key",data);

Related

How to check if url with parameter match with the filename in ignore array

Am creating a web page that used ajax to load content and localCache technique to store loaded page for later use. Everything seems to work well except that i will like to ignore some page which i have also implemented a simple method to do that but the problem is when the URL is full https://example.com/view_item.php it won't ignore it but view_item.php it will ignore. and also some page that has url parameter it won't ignore it too view_item.php?item=123, view_item.php?item=123&title=abc or https://example.com/view_item.php?item=123 etc because i can't add those url in ignore array as it do change. I suggest that this can be archived using regex but am not show how.
var localCache = {
data: {},
remove: function (url) {
delete localCache.data[url];
},
exist: function (url) {
return localCache.data.hasOwnProperty(url) && localCache.data[url] !== null;
},
get: function (url) {
console.debug('fatching data from URL ', url);
return localCache.data[url];
},
set: function (url, check, cachedData, callback) {
if(this.ignore(check)){
console.debug('Need To Ignore URL ', check);
}else{
localCache.remove(url);
localCache.data[url] = cachedData;
console.debug('caching data from URL ', url);
if ($.isFunction(callback)) callback(cachedData);
}
},
ignore: function(url){
var Arrays = [
'cart.php',
'favorites.php',
'view_item.php'
];
return ($.inArray( url, Arrays ) !== -1);
}
};

What are possible techniques to cache an Ajax response in Javascript? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am implementing a Javascript module manager that loads javascript files via XHR object. The problem of this method is resources caching:
Firstly, XHR rely on in-built browser caching mechanism which is OK but it's behaviour depends on the browser implementation.
Also there is a localStorage and there is a basket.js which uses localStorage to cache downloaded scripts, the problem is in limited size of storage which is usually 5-10MB. Besides, localStorage is a shared place for many scripts which also use it to store data.
And there is a Cache interface of the ServiceWorker API, but it is available only in ServiceWorker runtime so it doubtingly fit my needs.
Do anyone know some smart old or new javascript caching technique he's using in his project, or maybe heard of?
Note: Please, don't propose to use jQuery .ajax which is an interface to XHR, or any other library that implements an interface to in-built Javascript features.
Edit: There have been some valuable proposes:
Use library called localForage. The library represents a unified API to IndexedDB, WebSQL and localStorage, which one is used depends on browser.
Use IndexedDB which is truly powerfull storage with no significant space limits. The only concern is that only modern browsers implement IndexedDB.
This is specific for JQUERY....
Your can make ajax set up as cached.
$.ajaxSetup({ cache: true});
and if for specific calls you don't want to make cached response then call
$.ajax({
url: ...,
type: "GET",
cache: false,
...
});
If you want opposite (cache for specific calls) you can set false at the beginning and true for specific calls
If you want to store the result of ajax response, you can make use of Local Storage. All the modern browsers provides you storage apis. You can use them (localStorage or sessionStorage) to save your data.
All you have to do is after receiving the response store it to browser storage. Then next time you find the same call, search if the response is saved already. If yes, return the response from there; if not make a fresh call.
Smartjax plugin also does similar things; but as your requirement is just saving the call response, you can write your code inside your jQuery ajax success function to save the response. And before making call just check if the response is already saved.
Since indexeddb is a method used for storing data client-side, allows indexed database queries.
And this are the supported browsers
http://caniuse.com/#feat=indexeddb
And this are the only issues
Firefox (prior to version 37) and Safari do not support IndexedDB inside web workers.
Not supported in Chrome for iOS or other iOS WebViews.
Chrome 36 and below did not support Blob objects as indexedDB values.
Here is another similar polyfill you can try, but in my (albeit limited) experience, both polyfills are buggy/incomplete. They both also have many open issues on GitHub of people reporting problems. And when I tested one of them (I forget which one) it was significantly slower than native IndexedDB.
Maybe it's possible to create a decent polyfill, but the current ones don't seem to be doing the job.
Should I use WebSQL which was deprecated?
The problem with WebSQL is that it's never going to be supported in IE or Firefox. You could probably get away with WebSQL if you're only targeting mobile browsers, at least until Firefox OS or Windows Phone grabs significant market share.
Are there any plans to support IndexedDB in the future for all the non-supported browsers?
Let's be clear. You're asking about Apple, since everyone else supports IndexedDB in their latest browser (iOS Chrome uses Apple's rendering engine because Apple won't let them do anything else).
Not only does Apple not support IndexedDB, they haven't publicly said anything about it (as far as I can tell... and I have done a fair amount of searching). Which seems pretty weird. So as best I can tell, nobody has any idea if Apple ever plans to support IndexedDB. The conspiracy theorist in me thinks maybe they're trying to sabotage HTML5 apps to force people to write native apps, but that's purely speculation.
In total, this leaves us developers in a pretty shitty situation. There is no good cross-platform solution. I recommend you complain to Apple about it. That's what I've done, and I've asked my users who want to use my IndexedDB-based app on iOS to do the same. Still no word from Apple.
UPDATE - Indexeddb is now supported in iOS 8 as stated in WWDC 2014 - but unfortunately it's broken pretty badly.
Considerin also that Subresource Integrity -
Subresource Integrity enables browsers to verify that file is delivered without unexpected manipulation.
Does not have knowissues? so far ?
The i will suggest that you can go with
Subresource based solution if mobile is your main target
indexeddb if mobile is not your main target and use of the publicly available implementations for mobile
If all of the above sound too complex for you then
var localCache = {
data: {},
remove: function (url) {
delete localCache.data[url];
},
//a cached version exists
exist: function (url) {
return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout);
},
get: function (url) {
console.log('Getting in cache for url' + url); //log only!
return localCache.data[url].data;
},
set: function (url, cachedData, callback) {
localCache.remove(url);
localCache.data[url] = {
_: new Date().getTime(),
data: cachedData
};
if ($.isFunction(callback)) callback(cachedData);
},
timeout: 600, //in seconds
};
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
if (options.cache) {
var complete = originalOptions.complete || $.noop,
url = originalOptions.url;
//remove jQuery cache as you have your own localCache
options.cache = false;
options.beforeSend = function () {
if (localCache.exist(url)) {
complete(localCache.get(url));
return false;
}
return true;
};
options.complete = function (data, textStatus) {
localCache.set(url, data, complete);
};
}
});
$(function () {
var url = 'your url goes here';
$('#ajaxButton').click(function (e) {
$.ajax({
url: url,
data: {
test: 'value'
},
cache: true,
complete: doSomething
});
});
});
//ToDo after ajax call finishes, or cached version retrived
function doSomething(data) {
console.log(data);
}
Another specific JQUERY answer ?
Not sure it answers your question but that could help. It s caching ajax calls with a timeout.
In the prefiltering, list the various PHP ajax calls you want to add for caching.
In this example, cache is enabled with a 10 minutes timeout.
/*----------------------------*/
/* set ajax caching variables */
/*----------------------------*/
$.set_Ajax_Cache_filters = function () {
var localCache = {
timeout: 600000, // 10 minutes
data: {}, //#type {{_: number, data: {}}}
remove: function (url) {
delete localCache.data[url];
},
exist: function (url) {
return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout);
},
get: function (url) {
return localCache.data[url].data;
},
set: function (url, cachedData, callback) {
localCache.remove(url);
localCache.data[url] = {
_: new Date().getTime(),
data: cachedData
};
if ($.isFunction(callback))
callback(cachedData);
}
};
/*----------------------*/
/* set ajax pre filters */
/*----------------------*/
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
// list of allowed url to cache
if (url !== '..............file.php') {
return false;
}
if (options.cache) {
var complete = originalOptions.complete || $.noop,
url = originalOptions.url;
options.cache = false;//remove jQuery cache using proprietary one
options.beforeSend = function () {
if (localCache.exist(url)) {
complete(localCache.get(url));
return false;
}
return true;
};
options.complete = function (data, textStatus) {
localCache.set(url, data, complete);
};
}
});
};
To do this, the best technic is using local cache, ajaxPrefilter and ajax cache option, the combination of these three will create you the solid cache you want, that you can easily control
Here is a code example:
var localCache = {
data: {},
remove: function (url) {
delete localCache.data[url];
},
//a cached version exists
exist: function (url) {
return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout);
},
get: function (url) {
console.log('Getting in cache for url' + url); //log only!
return localCache.data[url].data;
},
set: function (url, cachedData, callback) {
localCache.remove(url);
localCache.data[url] = {
_: new Date().getTime(),
data: cachedData
};
if ($.isFunction(callback)) callback(cachedData);
},
timeout: 600, //in seconds
};
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
if (options.cache) {
var complete = originalOptions.complete || $.noop,
url = originalOptions.url;
//remove jQuery cache as you have your own localCache
options.cache = false;
options.beforeSend = function () {
if (localCache.exist(url)) {
complete(localCache.get(url));
return false;
}
return true;
};
options.complete = function (data, textStatus) {
localCache.set(url, data, complete);
};
}
});
$(function () {
var url = 'your url goes here';
$('#ajaxButton').click(function (e) {
$.ajax({
url: url,
data: {
test: 'value'
},
cache: true,
complete: doSomething
});
});
});
//ToDo after ajax call finishes, or cached version retrived
function doSomething(data) {
console.log(data);
}
Enjoy your coding
Try this might work
var cache = {};
var formatTweets(info) {
//formats tweets, does whatever you want with the tweet information
};
//event
$('myForm').addEvent('submit',function() {
var handle = $('handle').value; //davidwalshblog, for example
var cacheHandle = handle.toLowerCase();
if(cache[cacheHandle] != "undefined") {
formatTweets(cache[cacheHandle]);
}
else {
//gitter
var myTwitterGitter = new TwitterGitter(handle,{
count: 10,
onComplete: function(tweets,user) {
cache[cacheHandle] = tweets;
formatTweets(tweets);
}
}).retrieve();
}
});

How do I get Mercury Editor to redirect to a new resource?

After watching RailsCast #296 about Mercury Editor, I am trying to get the editor to redirect to a newly created resource.
I can already redirect on the client-side using JS and window.location.href=. But for a new resource, I cannot "guess" its URL on the client-side. I need it to be in the server response.
However, the problem is that I don't see the possibility of using the server response in the editor. No matter what the controller renders, the server response is discarded by Mercury instead of used as an argument to my function for mercury:saved.
Is there a way to get around this?
I was able to do this on update by sending a valid JSON string back. I would assume create works the same way. check firebug to make sure you're not getting an error in the jQuery.ajax call that Mercury uses.
posts_controller.rb
def mercury_update
post = Post.find(params[:id])
post.title = params[:content][:post_title][:value]
post.body = params[:content][:post_body][:value]
post.save!
render text: '{"url":"'+ post_path(post.slug) +'"}'
end
mercury.js:
jQuery(window).on('mercury:ready', function() {
Mercury.on('saved', function() {
window.location.href = arguments[1].url
});
});
note: I'm using friendly_id to slug my posts
Redirecting on the server side doesn't work because the save button is just an jQuery.ajax call:
// page_editor.js
PageEditor.prototype.save = function(callback) {
var data, method, options, url, _ref, _ref1,
_this = this;
url = (_ref = (_ref1 = this.saveUrl) != null ? _ref1 : Mercury.saveUrl) != null ? _ref : this.iframeSrc();
data = this.serialize();
data = {
content: data
};
if (this.options.saveMethod === 'POST') {
method = 'POST';
} else {
method = 'PUT';
data['_method'] = method;
}
Mercury.log('saving', data);
options = {
headers: Mercury.ajaxHeaders(),
type: method,
dataType: this.options.saveDataType,
data: data,
success: function(response) {
Mercury.changes = false;
Mercury.trigger('saved', response);
if (typeof callback === 'function') {
return callback();
}
},
error: function(response) {
Mercury.trigger('save_failed', response);
return Mercury.notify('Mercury was unable to save to the url: %s', url);
}
};
if (this.options.saveStyle !== 'form') {
options['data'] = jQuery.toJSON(data);
options['contentType'] = 'application/json';
}
return jQuery.ajax(url, options);
};
So your redirect is sent to the success callback, but the page doesn't actually re-render, as with any successful AJAX request. The author discusses overriding this very function here. It also looks like there might be some room to maneuver here by passing a callback function to save.
Btw, another way to do what #corneliusk suggests is:
render { json: {url: post_path(post.slug)} }
Either way, the response body is passed as an argument to the function in the mercury:saved callback.

How to override Backbone.sync so it adds the apikey and username at the end?

I am using backbone-tastypie, but I am having the toughest time getting it to work properly. In Tastypie, I am using ApiKeyAuthentication for my resources, so every ajax request, I need to append the apikey and username to the end of a request or send additional headers that add on the username and api key.
I am trying to remove a view and its model using backbone with the following code:
// Remove the goal update view from the DOM
removeItem: function() {
this.model.destroy({wait: true, success: function() {
console.log("success");
}, error: function() {
console.log("error");
}});
},
After the function executes, the browser tries to do a GET request on the following URL:
:8000/api/v1/update/2/
It does not include the api_key or username at the end, and it has a trailing slash at the end of the url. I think it is trying to use Backbone.oldSync to do the GET request. How would I make it so the sync does include the username/api key at the end and removes the trailing slash?
In all of the other requests, I have made it so the api key and username is appended to the end of the http request by adding the following code to backbone-tastypie:
if ( !resp && ( xhr.status === 201 || xhr.status === 202 || xhr.status === 204 ) ) { // 201 CREATED, 202 ACCEPTED or 204 NO CONTENT; response null or empty.
var location = xhr.getResponseHeader( 'Location' ) || model.id;
return $.ajax( {
url: location + "?" + "username=" + window.app.settings.credentials.username + "&api_key=" + window.app.settings.credentials.api_key,
success: dfd.resolve,
error: dfd.reject,
});
}
Let's explore the possibilities
Using headers
Backbone.sync still just uses jQuery ajax so you can override ajaxSend and use headers to send information along.
$(document).ajaxSend(function(e, xhr, options)
{
xhr.setRequestHeader("username", window.app.settings.credentials.username);
xhr.setRequestHeader("api_key", window.app.settings.credentials.api_key);
});
Using Ajax Options
If you need to send the information in just one or two locations, remember that the destroy, fetch, update and save methods are just shortcuts to the ajax caller. So you can add all jQuery ajax parameters to these methods as such:
// Remove the goal update view from the DOM
removeItem: function ()
{
this.model.destroy({
wait: true,
success: function ()
{
console.log("success");
},
error: function ()
{
console.log("error");
},
data:
{
username: window.app.settings.credentials.username,
api_key: window.app.settings.credentials.api_key
}
});
}
Overriding jQuery's ajax method
Depending on your needs, this might be the better implementation (note that this is no production code, you may need to modify this to fit your needs and test this before using it)
(function ($) {
var _ajax = $.ajax;
$.extend(
{
ajax: function (options)
{
var data = options.data || {};
data = _.defaults(data, {
username: window.app.settings.credentials.username,
api_key: window.app.settings.credentials.api_key
});
options.data = data;
return _ajax.call(this, options);
}
});
})(jQuery);
Just for future readers of this post, when you do a model.destroy() you can't pass any data because the delete request doesn't have a body, see this issue for more info:
https://github.com/documentcloud/backbone/issues/789

I can't to process response to a jsonp request

I have url http://translate.google.ru/translate_a/t?client=x&text=enter text&sl=en&tl=pl
If you will go through this link in response you will have js file
with text:
{"sentences":[{"trans":"wprowadzania tekstu","orig":"enter text","translit":"","src_translit":""}],"src":"en","server_time":80}
I created ajax request
function GoogleTranslateItem(sourceText, langFrom, langTo) {
$.ajax({
url: 'http://translate.google.ru/translate_a/t',
data: { client: "x", text: sourceText, sl: langFrom, tl: langTo },
dataType: 'jsonp',
jsonpCallback: "getData",
success: function (data) {
alert("Success");
}
});
function getData(data) {
var dataJson = data;
alert('bingo');
}
when the answer comes from server. I can't to process it
in browser shows js error.
Syntax error at line 1 while loading:
{"sentences":[{"trans":"вход вых
------------^
expected ';', got ':'
Linked script compilation
How can i process this response?
I think you should take a look at this (http://javascriptweblog.wordpress.com/2010/11/29/json-and-jsonp/)
var jsonp = {
callbackCounter: 0,
fetch: function(url, callback) {
var fn = 'JSONPCallback_' + this.callbackCounter++;
window[fn] = this.evalJSONP(callback);
url = url.replace('=JSONPCallback', '=' + fn);
var scriptTag = document.createElement('SCRIPT');
scriptTag.src = url;
document.getElementsByTagName('HEAD')[0].appendChild(scriptTag);
},
evalJSONP: function(callback) {
return function(data) {
var validJSON = false;
if (typeof data == "string") {
try {validJSON = JSON.parse(data);} catch (e) {
/*invalid JSON*/}
} else {
validJSON = JSON.parse(JSON.stringify(data));
window.console && console.warn(
'response data was not a JSON string');
}
if (validJSON) {
callback(validJSON);
} else {
throw("JSONP call returned invalid or empty JSON");
}
}
}
}
The response from http://translate.google.ru/translate_a/t?client=x&text=entertext&sl=en&tl=pl i JSON, not JSON-P. Accessing JSON-data this way is against the cross-site policies, as the browsers prevent such responses to be returned to the client.
As you are allowed to include scripts from other domains, JSON-P is a way of transfering data as javascript (not JSON). You need to find an API supporting JSON-P (I'm not sure if the Translate API supports JSON-P) or create a proxy on the same domain as your client application to access the JSON data.
Read more about the JSON-P protocol here: http://json-p.org/
To create a proxy, you'll need to implement a service that fetches the content of the Translate API and reprint it in the response.
Example:
/jsonProxy?text=foo
Should return the contents of http://translate.google.ru/translate_a/t?client=x&text=entertext&sl=en&tl=pl
...but you won't have to access it from another domain.
I think the MIME type of the response should be 'application/json'

Categories

Resources