Ready state is still 1 though I got the Response - javascript

toggleCompletedCheck : function(e) {
e.stopPropagation();
e.stopImmediatePropagation();
var key = $(e.currentTarget).attr("id");
this.model = todoCollection.findWhere({
key : key
});
this.model.toggle("completed", true);
this.option.collection = todoCollection.add(this.model);
var email = this.model.get("email");
var title = this.model.get("title");
var key = this.model.get("key");
var status = this.model.get("status");
var completed = this.model.get("completed");
this.updateUserData(email, key, title, completed, status);
returnValue = this.model.save();
console.log(returnValue);
},
The ready state is still 1 with in the function. The variable which I used is a window object(returnValue). When I print the object again in the console(from chrome browser) it shows me ready state 4 also allows me to access the responseText using returnValue.responseText. I am using the backbone.js to save the input to the backend. That returns the responseText as saved. But in turn, I am unable to access it when I try to it says undefined. How to get the responseText that I needed with in this function.

Backbone's model.save() method is asyncronous. It returns a value (the javascript xhr object), but the request is not complete at return time.
To use the completed response, you would usually pass success or error callbacks to the save method (docs here):
this.model.save(null, {
success: function(model, response, options) {
// do something with the response
},
error: function(model, response, options) {
// do something with the response
}
});
This can be a bit of an adjustment when you are used to returning responses from your functions, but equivalent functionality is almost always possible using callbacks.

Related

Save JavaScript prototype based objects in sessionStorage?

var obj = {
conn : null,
first : function(thisIdentity) {
"use strict";
var myObj = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function(data) {
myObj.conn = new Connection(data.user_id, "127.0.0.1:80");
sessionStorage.setItem('connection', JSON.stringify(myObj.conn));
}
});
},
second : function(thisIdentity) {
"use strict";
var myObj = this;
var conntn = sessionStorage.getItem('connection');
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function(data) {
var parsedConnection = JSON.parse(conntn);
parsedConnection.sendMsg(data.id, data.nid);
}
});
}
};
var Connection = (function() {
function Connection(uid, url) {
this.uid = uid;
this.open = false;
this.socket = new WebSocket("ws://"+url);
this.setupConnectionEvents();
},
Connection.prototype = {
sendMsg : function(id, nid) {
alert("Working");
},
// other functions
}
})();
So connection is made in the AJAX callback function of first and I store the object in the sessionStorage via JSON but when I use it in the AJAX callback of second then error is coming that
TypeError: parsedConnection.sendMsg is not a function
Now I understand that may be it is because JSON can be used to store plain objects not prototype-based objects.
My question is : Can any one tell me how to store prototype-based objects via JSON or any other way to implement this?
I don't want to use eval. Any code, reference would be much appreciated. Thanks!
UPDATE
I did as #Dan Prince mentioned but then a new problem occurred that now when in sendMsg function I use
this.socket.send(JSON.stringify({
action: 'message',
rec: receiver,
msg: message
}));
Then it stays
InvalidStateError: An attempt was made to use an object that is not,
or is no longer, usable
Any inputs? Thanks!
You could probably hack your own solution into place by storing the prototype as a property of the object, then reinstantiating it with Object.create after you read it, but the real question is why do you want to do this in the first place?
I would suggest writing a serialize method on Connection's prototype, which exposes only the essential information (there's no sense serializing a web socket for example).
Connection.prototype.toJSON = function() {
return JSON.stringify({
uid: this.uid,
url: this.url,
open: this.open
});
};
Then use this method when you save the connection object into session storage.
myObj.conn = new Connection(data.user_id, "127.0.0.1:80");
sessionStorage.setItem('connection', myObj.conn.toJSON());
Each saved connection now has the minimum amount of data you need to call the constructor and recreate the instance.
When you load a connection from session storage, parse it and pass the values back into the constructor.
var json = sessionStorage.getItem('connection');
var data = JSON.parse(json);
var connection = new Connection(data.uid, data.url)
// ...
connection.sendMsg(data.id, data.nid);
This will recreate the correct prototype chain in a natural and predictable way.
It's hard to see exactly what you are trying to achieve in every respect, but let's assume :
for various DOM elements, a click handler (delegated to document) will cause asynchronously derived data to be sent via socket.send().
the socket is to be initialized with an asynchronously derived uri.
the socket is to be kept available for immediate reuse.
data by which the socket is initialized is to be cached in local storage for future sessions. (It makes no sense to store the socket itself).
In addition, we need to acknowledge that a socket consume resources should really be disposed of if its resuse is not immediate.
The whole strategy is abnormally complex. The overhead of performing an ajax operation once per session to obtain a uri would typically be accepted, as would the creation of a socket each time one is needed. However, it's an intersting exercise to write something with all the stated characteristics.
This may not be 100% correct but could possibly give you some ideas, including the use of promises to cater for several asynchronisms. Here goes ...
var obj = {
conn: null,
init: function(thisIdentity) {
// It makes sense to attach the click handler only *once*, so let's assume this is an init function.
"use strict";
var myObj = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
}).then(function(data) {
myObj.send(JSON.stringify({
'id': data.id,
'nid': data.nid
}));
});
});
},
send: function(data) {
"use strict";
var myObj = this;
return myObj.getSocket().then(function(socket) {
socket.send(data);
}).then(function() {
// by disposing in later event turn, a rapid series of send()s has at least a chance of using the same socket instance before it is closed.
if(socket.bufferedAmount == 0) { // if the socket's send buffer is empty, then dispose of it.
socket.close();
myObj.conn = null;
}
});
},
getSocket: function() {
"use strict";
var myObj = this;
//1. Test whether or not myObj.conn already exists ....
if(!myObj.conn) {
//2 .... if not, try to recreate from data stored in local storage ...
var connectionData = sessionStorage.getItem('connectionData');
if(connectionData) {
myObj.conn = myObj.makeSocket(connectionData.user_id);
} else {
//3. ... if connectionData is null, perform ajax.
myObj.conn = $.ajax({
url: some value,
// other parameters
}).then(function(data) {
sessionStorage.setItem('connectionData', JSON.stringify(data));
return myObj.makeSocket(data.user_id);
});
}
}
return myObj.conn; // note: myObj.conn is a *promise* of a socket, not a socket.
},
makeSocket: function(uid) {
"use strict";
var myObj = this;
var uri = "127.0.0.1:80"; // if this is invariant, it can be hard-coded here.
// return a *promise* of a socket, that will be resolved when the socket's readystate becomes OPEN.
return $.Deferred(function(dfrd) {
var socket = new WebSocket("ws://" + uri);
socket.uid = uid;
socket.onopen = function() {
myObj.setupConnectionEvents();// not too sure about this as we don't know what it does.
dfrd.resolve(socket);
};
}).promise();
}
};
Under this scheme, the click handler or anything else can call obj.send() without needing to worry about the state of the socket. obj.send() will create a socket if necessary.
If you were to drop the requirement for storing data between sessions, then .send() and .getSocket() would simplify to the extent that you would probably choose to roll what remains of .getSocket() into .send().

multiple calls to ajax simultaneously

I'm trying to make multiple calls to Ajax, i have fields like time intervals and no of calls to ajax under that time period. Now the problem is, while making multiple calls to same Ajax, there may be chances of merging of data with the other data that were send to Ajax earlier. I am not sure that it will happen.
Here my Ajax call.
callAjax = function () {
var dataIn = inObj.data || {};
var successFunc = inObj.success || function () {};
var passOn = inObj.passOn || {};
var myParams = {drape:1,type:'GET'};
myParams.url = this.homeComingUrl;
$.extend(myParams,params);
var data = this.fillAction(action,dataIn);
if (myParams.drape) { vidteq.utils.drapeSheer(action); }
var that = this;
var magicCall = $.ajax({
url:myParams.url,
type:myParams.type,
data:data,
success: function (response) {
// TBD we need better error handling
if (myParams.drape) { vidteq.utils.undrapeCurtain(action); }
successFunc(response,passOn);
},
error:function(response) {
if (myParams.drape) { vidteq.utils.undrapeCurtain(action); }
that.gui.io.handleError(response);
}
});
}
saveEvents = function () {
this.commitEditingEvent();
var dataEvents = this.collectEventsToSave();
//$('#calendar').fullCalendar('removeEvents');
var that = this;
if (vidteq.eTrainer==1) {
dataEvents = arguments[0];
}
if (!dataEvents.length) { alert("Nothing to save");return; }
this.callAjax('updateEvents',{
data : { events : JSON.stringify(dataEvents) },
success : function (response,passOn) {
that.handleGetEvent(response,passOn);
}
},{type:'POST'});
}
This may not be required for understanding the problem.
If any body can explain how Ajax handles multiple calls, then it'll really helpful.
First line, your anonymous function isn't saved and isn't ran. Then. In each function, what does this refer to ? What is this context ? Is this window or do you call your function like saveEvents.apply( jQuery ) ?
JavaScript is powerful, when your want to run XMLHttpRequest (Ajax uses it), scripts are called when an event happen, like "server is found", "request is send", "file is reading", "file loaded"... for each state of your request. Ajax by jQuery help you to request asynchronous. You can request as many Ajax request as you would like in the same time. The important is to create a function happen in success case.
In this success function, you receive data, you compute it, then this function may call another Ajax request, and so on. When you chain requests like this to get the same file, we call it Ressource.
Ressource uses Ajax which uses XMLHttpRequest.
you need to do asynic :false in your ajax method
function isLoggedIn() {
var isLoggedIn;
$.ajax({
async: false,
// ...
success: function(jsonData) {
isLoggedIn = jsonData.LoggedIn
}
});
return isLoggedIn
}

dojoJS Solr connector - pass out (return) data

I am new to accessing json data from rest services like Solr and ElasticSearch with JS and the dojo framework.
In this case I have used dojo to write solr.js which contains a simple function that uses JSONP params with dojo.io.script to connect to a Solr index. Now I need to get the function to pass out (return) the data that gets from Solr. This is how I want to call the function:
<script src="solr.js"></script>
<script>
var mySolrData = solrStore(
"http://solrUrl/",
"indexName/select"
);
</script>
This is the code for the solr.js file that contains the function I am calling:
dojo.require("dojo.io.script");
function solrStore (indexURL, collectionPath, wt, rows, start, q) {
//set some default values//
wt = typeof wt !== 'undefined' ? wt : 'json';
rows = typeof rows !== 'undefined' ? rows : '25';
start = typeof start !== 'undefined' ? start : '1';
q = typeof q !== 'undefined' ? q : '*';
//arguments for jsonp to connect to solr index//
var jsonpArgs =
{
url: indexURL + collectionPath,
labelAttribute:"solr",
handleAs: "json",
callbackParamName: "json.wrf",
content: {
wt: wt,
rows: rows,
start: start,
q: q
//end content vars//
},
//load the data
load: function(data){
//set the value of the raw response data
var mySolrStore = data;
//view the data in the console
console.log(mySolrStore.response.docs);
return mySolrStore.response;
//end load data//
},
//on error show in the console
error: function(error){
console.log("An error occured connecting to the Solr index: " + error);
//end on error
}
//end arguments for jsonp
};
//get the data with dojo.io.script.get
dojo.io.script.get(jsonpArgs);
}
When I execute the code in the browser I see the data that need in the console log when it hits the load: part. However, I am having a brain-fart on how I can pull that data out of the function into the page where I call the function because no matter how I try it says it is undefined.
What am I missing that I need to do to get the data I retrieve from the solrStore function into the mySolrData var?
The variable mySolrStore is defined inside the asynchronous function "load:".
If I am not wrong you cannot return(catch values) from an asynchronous function since the context is different.
//set the value of the raw response data
var mySolrStore = data;
I would suggest that you define the variable outside the "load:". For instance you could define it before and
var mySolrStore;
//arguments for jsonp to connect to solr index//
var jsonpArgs = .....
and set the data value inside the load: call.
load: function(data){
//set the value of the raw response data
mySolrStore = data;
Hope it solves issue.

Cannot parse JSON?

Here's my javascript file
var callAjax = function(relative_path){
var Ajax = new XMLHttpRequest();
Ajax.onreadystatechange = function() {
//Since what we are calling a local file. we cannot get a 200 OK Status.
//So We check only the readystate
if(Ajax.readyState==4){
serialized = Ajax.responseText;
alert(serialized);
// ^^ alerts fine.
return serialized;
}
}
Ajax.open("GET",relative_path, true);
Ajax.send();
};
var readSettings = function(){
var data = callAjax('settings.json');
obj = JSON.parse(data);
alert(obj);
}
Now when i call readSettings() somewhere in my html, the first alert (in the callAjax functions alerts the JSON correctly. but the second one does not. When i see the console, the error is :
[21:04:02.233] SyntaxError: JSON.parse: unexpected character # file:///home/cipher/Codes/looma-f5/js/looma.js:23
My settings.json is:
{
"classes": 8,
"config": "classConfig",
"locale": {
"en": "localeEn"
},
"defaultLocale": "en"
}
I ran the JSON through online tools, it looks good. Why is firefox not parsing these?
You're not returning any value from the callAjax function. You need to put your code that uses the result inside the onreadystatchange handler.
You do have a return statement, but it's inside the callback, which returns to the internal caller of the callback, and which is invoked after your callAjax returned.
Since it seems that callAjax is fairly generic, a good approach is to have that function accept a callback as an argument, then invoke it, passing in the response.
// receive a callback----vv
var callAjax = function(relative_path, callback){
var Ajax = new XMLHttpRequest();
Ajax.onreadystatechange = function() {
if(Ajax.readyState==4){
serialized = Ajax.responseText;
alert(serialized);
// vv---invoke the callback
callback(serialized);
}
}
Ajax.open("GET",relative_path, true);
Ajax.send();
};
var readSettings = function(){
// pass a callback ----------------------vv
var data = callAjax('settings.json', function(data) {
var obj = JSON.parse(data);
alert(obj);
});
}
If the caller of readSettings needs to work with the response, then you could have readSettings also receive a callback, and then either pass it on directly, or wrap it in another function so that it can first do the parsing.
I'll give an example that assumes that it needs to be wrapped.
// receive a callback----------vv
var readSettings = function(callback){
// pass a callback that wraps the first---vv
var data = callAjax('settings.json', function(data) {
// parse the response data
var obj = JSON.parse(data);
// invoke the callback, passing it the parsed object
callback(obj);
});
}
readSettings(function(settings_obj) {
alert(settings_obj);
});
The problem is that you can JSON.parse immediately after callAjax returns. Before the onreadystate callback is executed. Due to asynchronous nature of the operation you should trigger parsing from the callback.
The "A" in AJAX is for asynchronous. After submitting the XMLHttpRequest, the callAjax function will return immediately, without waiting for the request to complete. Thus, the JSON.parse will be called with the return value of callAjax (which isn't the JSON you're looking for), generating the error.
Some time later, the XMLHttpRequest will complete and the onreadystatechange callback will be run. You return the JSON from this function, but the JSON doesn't go anywhere because it's returning from the callback, not from callAjax.
You must perform the JSON parsing and subsequent activities as a result of the onreadystatechange event.

JavaScript function within a function - returning an object

I would like to call a function within a function and have this inner function return an object. I am using a JSONRequest function that I created myself so just assume that the request fetches an array of roles. Here is the code:
(users = function(){
this.getUserRoles = function(){
var params = {};
var json = new JSONRequest(function(data){
rolesObj = data['roles'];
return rolesObj;
}, 'get_roles', params);
}
});
Then I call the following but it returns undefined:
var cls = new users();
alert(cls.getUserRoles().length);
ajax requests are asynchronous so you're not going to get a return value from them. You do, however, receive a callback when they complete so you can pass your "return" value into a callback.
Here is an example of your code re-written to use a callback:
this.getUserRoles = function(completionCallback){
var params = {};
var json = new JSONRequest(function(data){
rolesObj = data['roles'];
completionCallback(rolesObj);
return rolesObj;
}, 'get_roles', params);
}
and then using it:
var cls = new users();
cls.getUserRoles(function(roles) {
alert(roles.length);
});
The rolesObj is passed into the callback function once the JSON request completes.
Your getUserRoles function doesn't return anything. It invokes an asynchronous JSON request, and the success callback for that request returns something.
There is no way to make an asynchronous request in a function and have the function synchronously return a value from the request. The request will take an unknown amount of time, and the requesting function will return as soon as the request has been sent. The value won't have arrived back from the server yet.

Categories

Resources