HTTP Requests

    The XMLHttpRequest object allows the user to register a response handler function and a URL. A request can be sent using one of the HTTP verbs (get, post, put, delete, …) to make the request. When the response arrives the handler function is called. The handler function is called several times. Every-time the request state has changed (for example headers have arrived or request is done).

    Here a short example:

    For a response, you can get the XML format or just the raw text. It is possible to iterate over the resulting XML but more commonly used is the raw text nowadays for a JSON formatted response. The JSON document will be used to convert text to a JS object using JSON.parse(text).

    1. ...
    2. } else if(xhr.readyState === XMLHttpRequest.DONE) {
    3. var object = JSON.parse(xhr.responseText.toString());
    4. print(JSON.stringify(object, null, 2));
    5. }

    In the response handler, we access the raw response text and convert it into a javascript object. This JSON object is now a valid JS object (in javascript an object can be an object or an array).

    It seems the toString() conversion first makes the code more stable. Without the explicit conversion, I had several times parser errors. Not sure what the cause it.

    Let us have a look on a more real-world example. A typical example is to use the Flickr service to retrieve a public feed of the newly uploaded pictures. For this, we can use the http://api.flickr.com/services/feeds/photos_public.gne URL. Unfortunately, it returns by default an XML stream, which could be easily parsed by the XmlListModel in qml. For the sake of the example, we would like to concentrate on JSON data. To become a clean JSON response we need to attach some parameters to the request: http://api.flickr.com/services/feeds/photos_public.gne?format=json&nojsoncallback=1. This will return a JSON response without the JSON callback.

    TIP

    A JSON callback wraps the JSON response into a function call. This is a shortcut used on HTML programming where a script tag is used to make a JSON request. The response will trigger a local function defined by the callback. There is no mechanism which works with JSON callbacks in QML.

    The response will be something like this:

    1. {
    2. "title": "Recent Uploads tagged munich",
    3. "items": [
    4. {
    5. "media": {"m":"http://farm8.staticflickr.com/7313/11444882743_2f5f87169f_m.jpg"},
    6. ...
    7. },{
    8. "title": "Munich after sunset: a train full of \"must haves\" =",
    9. "media": {"m":"http://farm8.staticflickr.com/7394/11443414206_a462c80e83_m.jpg"},
    10. ...
    11. }
    12. ]
    13. ...
    14. }

    The returned JSON document has a defined structure. An object which has a title and an items property. Where the title is a string and items is an array of objects. When converting this text into a JSON document you can access the individual entries, as it is a valid JS object/array structure.

    As a valid JS array, we can use the obj.items array also as a model for a list view. We will try to accomplish this now. First, we need to retrieve the response and convert it into a valid JS object. And then we can just set the response.items property as a model to a list view.

    1. xhr.onreadystatechange = function() {
    2. if(...) {
    3. ...
    4. } else if(xhr.readyState === XMLHttpRequest.DONE) {
    5. var response = JSON.parse(xhr.responseText.toString());
    6. // set JS object as model for listview
    7. view.model = response.items;
    8. }
    9. }
    10. xhr.open("GET", "http://api.flickr.com/services/feeds/photos_public.gne?format=json&nojsoncallback=1&tags=munich");
    11. xhr.send();

    Here is the full source code, where we create the request when the component is loaded. The request response is then used as the model for our simple list view.

    The other option would be to have a placeholder and append each item onto the list model. To support larger models it is required to support pagination (e.g page 1 of 10) and lazy content retrieval.