1

I am passing a JSON from a Python back-end into my front-end JavaScript where I'm running a webGL (three.js) animation. The JSON holds numerical values that determine what happens in the animation. My problem is that while I have a basic ajax request working, the JSON is being printed to the screen (in lieu of the animation) rather than becoming a variable I can iterate through to control aspects of the animation. The two halves of the call are shown below.

I asked a related question to this one before and got some great help, but am obviously still missing a piece of the puzzle. I've been reading docs and all sorts of sources, yet need a nudge in the right direction to finally get this working. Any help is appreciated!

In the python backend:

from flask import Response, json, render_template, jsonify
from app import app
from motifs import get_motif, get_motif_list

@app.route('/')
def index():
    motifs = get_motif_list(10)
#     The first version of the return below successfully sends data, yet it is printed to the 
#     screen, rather than being stored as data in a variable.
    return Response(json.dumps(motifs), mimetype='application/json')
#     This version of the return does not work:
#     return render_template("index.html", motifs = motifs) 

In the JavaScript (note that the console.log sanity checks don't work - I have no idea why:

function foo() {
    var array_data;

    $.ajax({
        type: "GET",
        url: "/",
        dataType: "json"
    });

    request.done(function(JSON_array) {
        array_data = JSON.parse(JSON_array)["array"]
        console.log(array_data); // sanity check - doesn't work
    });
    return array_data;
};

var array = foo();
console.log(array); // sanity check - doesn't work

UPDATE

With help from the advice below, I'm pretty close to having this off the ground. The JSON is no longer printing to the screen (an issue caused by the Flask return), and I've solved a multifunction callback issue I discovered along the way. However, I am now getting a parsererror from the complete textStatus. I think the problem now lays in the Python/Flask (see current code below). Thanks again for all who've helped!

Python/Flask (I think the problem is here - I'm a noob to Flask):

from flask import Response, json, render_template, jsonify
from app import app
from motifs import get_motif, get_motif_list

@app.route('/')
def index():
    motifs = get_motif_list(10)
    return Response(json.dumps(motifs), mimetype='application/json')

@app.route("/")
def index():
     return render_template("index.html")

The JavaScript (the data is returned by the Deferred object - used to solve a callback issue):

function getData() {

    var deferredData = new jQuery.Deferred();

    $.ajax({
        type: "GET",
        url: "/",
        dataType: "json",
        success: deferredData.resolve(),
        complete : function(xhr, textStatus) {
            console.log("AJAX REquest complete -> ", xhr, " -> ", textStatus)}
    });

    return deferredData; // contains the passed data
};
Community
  • 1
  • 1
gromiczek
  • 2,970
  • 5
  • 28
  • 49
  • 1
    `dataType: "json"` possibly already coerce your data into json. start by debugging in the request.done function. – njzk2 Apr 14 '14 at 17:46
  • 1
    `dataType: "json"` *already decodes* the response for you. – Martijn Pieters Apr 14 '14 at 17:47
  • 1
    Add the following callback to your ajax call and see what is logged to the console for textStatus. complete : function(xhr, textStatus){console.log("AJAX REquest complete -> ", xhr, " -> ", textStatus)} – Timigen Apr 14 '14 at 17:50
  • @gromiczek Does requirement include calling `JSON_array` after `foo()` completion, outside `scope` of `foo` ? Does requirement include `JSON_array` defined as global variable ? Thanks – guest271314 Apr 15 '14 at 02:10
  • @guest271314 - thanks for your question. In the end I need to pass the JSON_array into another module in the code, so yes I'll need to call it outside the scope of `foo`, but in the end it will not be global. I'm taking a while to solved this problem because I've also realized need to learn how to handle multiple callbacks in my script. I have another asynchonous (non ajax/jquery) request I need to handle along with this call to the database. – gromiczek Apr 15 '14 at 13:33
  • @guest271314 - Thanks! Pardon my taking so long on this - I also put out a question on the callbacks issue - http://stackoverflow.com/q/23085889/2441384 , so I've been painstakingly trying to weave all these matters together. Oi! – gromiczek Apr 15 '14 at 17:40
  • @guest271314 - Ugh, it's still displaying to the screen instead of saving as a variable. I've even commented out all the javascript code related to this request and it's still displaying. This is fishy. – gromiczek Apr 15 '14 at 18:47
  • @gromiczek Not certain interpret accurately ? `window.array_data` ? Try without `return false` at `async()` ? Please post pieces tried. Thanks – guest271314 Apr 15 '14 at 19:34
  • @guest271314 - Sorry, the 'it' was the JSON object. I discovered that I needed to use the second return in python: `return render_template("index.html", motifs = motifs)` to stop that problem. – gromiczek Apr 15 '14 at 19:40
  • @guest271314 - added an update. – gromiczek Apr 15 '14 at 19:48
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/50724/discussion-between-guest271314-and-gromiczek) – guest271314 Apr 15 '14 at 20:03

2 Answers2

3

It turns out I had a lot of problems in my code above, several of which I had to debug in related questions here and here.

Among them were:

  • in my original Flask index() function, it was dumping the JSON data to the screen because I was not rendering the index.html template anywhere.
  • I had matching routes ('/') and function names (index()) in the Flask functions
  • As mentioned in the comments I did an unnecessary double parsing of the JSON with dataType: json and array_data = JSON.parse(JSON_array)
  • the return from this asynchonous function always came up undefined because it was referenced before the call had resolved
  • in my later update to a Deferred object, the success property should have read: success: function(data) { deferredData.resolve(data);}

So, after all those fixes, here is the functioning code!

Flask/Python:

from flask import Response, json, render_template, jsonify
from app import app
from motifs import get_motif, get_motif_list

@app.route('/ajax')
def ajax() :
    motifs = get_motif_list(10)
    return Response(json.dumps(motifs), mimetype='application/json')

@app.route("/")
def index():
     return render_template("index.html")

JavaScript: (note: this is the foo() function in my question above)

function getData() {

    var deferredData = new jQuery.Deferred();

    $.ajax({
        type: "GET",
        url: "/ajax",
        dataType: "json",
        success: function(data) { 
            deferredData.resolve(data);
            },
        complete: function(xhr, textStatus) {
            console.log("AJAX Request complete -> ", xhr, " -> ", textStatus);
            }
    });

    return deferredData; // contains the passed data
};


// I used the Deferred structure below because I later added Deferred objects from other asynchronous functions to the `.when`

var dataDeferred = getData();

$.when( dataDeferred  ).done( function( data ) {
    console.log("The data is: " + data);    
});
Community
  • 1
  • 1
gromiczek
  • 2,970
  • 5
  • 28
  • 49
  • I am facing the same problem. But, in my case, I am using plain JavaScript. So could you please help me how to use `Deferred` in plain JavaScript. Thanks in advance. – Angela Amarapala Aug 14 '17 at 05:05
0

In your javascript:

function foo() {
var array_data;

$.ajax({
    type: "GET",
    url: "/",
    dataType: "json"
});

request.done(function(JSON_array) {

    /*JSON_array is already parsed and it is an object..*/

    array_data = JSON.parse(JSON_array)["array"]
    /* ^ I belive you dont have to do this ^*/

    console.log(array_data);
    /* ^ change this to console.log(JSON_array);*/
});

return array_data;
/* ^ change this to return JSON_array;*/
};