Storing a JSON object
-
Hi,
I am stuck with my JSON object. I am able to get a JSON response from a server, see the code below. But I am unable to work with the retuned JSON object.
function get(url, task, id) { var xhr = new XMLHttpRequest(); xhr.open("GET",url,true); xhr.onreadystatechange = function(){ if ( xhr.readyState == xhr.DONE){ if ( xhr.status == 200){ var jsonObject = JSON.parse(xhr.responseText) if(task === "service"){ console.log(JSON.stringify(jsonObject)) // correct output of the object return jsonObject } } } } xhr.send(); }
In a QML file I try to put the object in a property:
property var event: Parser.get(accountModel.get(0).urlRead + "/api/app/v1/details.php?id="+ eventModel.get(eventModel.activeEvent).i +"&sids="+accountModel.get(0).sids, "service", 0) Label { text: eventPage.event["t"] } // [W] unknown:57 - file:///.../EventPage.qml:57: TypeError: Cannot read property 't' of undefined
The property event is always undefined. Is it not possible to put a JSON object in a property or am I just doing something wrong?
-
@Sikarjan
Okey, let's try another way.
Fix your code like this... xhr.send(); return { t: "yep" }; }
This is return from your function get().
Where you try to return it is another function, called from another place, with processing it's return value at place, where it has called asynchronously.
-
Also a thought: Since XMLHttpRequest will execute the query most likely asynchronously, you won't get your reply with JSON when the get() function finishes. Use your callback function to set the property event there(this means that the property also must be visible from there), like this:
function get(url, task, id, eventHolder) { var xhr = new XMLHttpRequest(); xhr.open("GET",url,true); xhr.onreadystatechange = function(){ if ( xhr.readyState == xhr.DONE){ if ( xhr.status == 200){ var jsonObject = JSON.parse(xhr.responseText) if(task === "service"){ console.log(JSON.stringify(jsonObject)) // correct output of the object //return jsonObject eventHolder.event = jsonObject } } } } xhr.send(); }
Item { id: myItem property var event Component.onCompleted: { Parser.get(accountModel.get(0).urlRead + "/api/app/v1/details.php?id="+ eventModel.get(eventModel.activeEvent).i +"&sids="+accountModel.get(0).sids, "service", 0, myItem) } }
-
You can use jsonCache.com or myjson.com to test you function. They are both easy to use and very usefull.
Regards,
NNCU -
Thanks for all your suggestions. I still do not 100 % the problem but I solved it similar to Jagh's suggestion. In stead of the line
eventHolder.event = jsonObject
I assign the jsonObject to a parameter in my main.qml. This variable is visible in all other pages of my program.
It still baffles me that I can assign the object to a variable but not return it. I see that XMLHttpRequest works asynchronously and that get will be finished first but the rest I do not understand.
-
@Sikarjan the key problem i think here is to understand, what happens when functions are treated as first class citizens. C++ does this too(with lambda syntax for instance), but it is way more common to see in JavaScript, a language that has functional roots.
In this example, we actually have 2 functions: one that is called get(url, task, id), and one that doesn't have a name(lambda function), its declaration begins with function(){... on line 4. To see it better, you could write the program from your first post as
function onReadyState(xhr, task) { if ( xhr.readyState == xhr.DONE){ if ( xhr.status == 200){ var jsonObject = JSON.parse(xhr.responseText) if(task === "service"){ console.log(JSON.stringify(jsonObject)) // correct output of the object return jsonObject } } } } function get(url, task, id) { var xhr = new XMLHttpRequest() xhr.open("GET", url, true) xhr.onreadystatechange = onReadyState.bind(null, xhr, task) xhr.send() }
As you can see here, you only have return statement in the first function(but you only directly call get) The onReadyState is not called in this code, .bind() only does here partial function application(basically the same as std::bind in C++).
JavaScript has quite good support for functional-style programming, and professionals use this extensively. If in C++ it's very rarely that you encounter something like an std::function<void(int, string)> type, use of functional idioms in JavaScript is very common place. You will get used to them in time.