0

I'm making a flask application. The user submits a form, which is sent to server. The server does something, and I am trying to append the results to the unordered list as they come in.

I'm trying to yield the results in flask and use XMLHttpRequest in my javascript file to append each item to an unordered list.

main.py:

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


@app.route('/search', methods=['GET', 'POST'])
def search_form():
    print(request.form)
    x = request.form['id']
    a = Vbulletin(x)

    def result_gen():
        return a.reg_ver()
    result_gen()

    def generate_resp():
        for text in result_gen():
            print(text)
            yield jsonify(text)
            sleep(1)

    return app.response_class(generate_resp(), mimetype='application/json')


app.run()

forumsearch.js:

$(document).ready(function(){
   $("#submit").on('click',function(e){
        e.preventDefault();
        req = $.ajax({type: "POST",
            url: "/search",
            data: { id: $("#searchinput").val()},
         });
        req.done(function(temp){
            alert("POST was sent.");

            var latest = document.getElementById('latest');
            var output = document.getElementById('output');

            var xhr = new XMLHttpRequest();
            xhr.open('GET', '/search');
            xhr.send();
            var position = 0;

            function handleNewData() {
                var messages = xhr.responseText.split('\n');
                messages.slice(position, -1).forEach(function(value) {
                    latest.textContent = value;
                    var item = document.createElement('li');
                    item.textContent = value;
                    output.appendChild(item);
                });
                position = messages.length - 1;
            }

            var timer;
            timer = setInterval(function() {

                handleNewData();

                if (xhr.readyState == XMLHttpRequest.DONE) {
                    clearInterval(timer);
                    latest.textContent = 'Done';
                }
            }, 1000);

            });
       });
  });

I'm having issues getting the response sent to the client, and am getting this error:

RuntimeError: Working outside of application context.

I changed generate_resp() to this:

def generate_resp():
    with app.app_context():
        for text in result_gen():
            print(text)
            yield jsonify(text)
            sleep(1)

Now I get this error:

AssertionError: applications must write bytes

At this point I'm unsure if adding 'app_context' solved my primary issue, and now I have a format problem to deal with, or if I never fixed anything in the first place. How can I fix this so the response is asynchronously sent to client?

Smitty
  • 165
  • 1
  • 11
  • 1
    To clarify, you want to send elements of an array one by one from server to client and have client load them into its own array one by one. Is that correct? If so, I'd suggest sending the entire array in one request because otherwise you're going to have a hard time. If each element of the array is that massive to warrant what you're suggesting, you probably should send separate requests... – 101arrowz Sep 24 '19 at 23:41
  • 1
    You define functions within the route handler and then immediately call them which is unnecessary and makes your code hard to follow. Why are you `yield`ing the jsonified text? That turns your function into a [generator](https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do). Also, you can directly return the jsonified data `return jsonify([your_data])`. Please explain what `a.reg_ver()` returns so we can help form your response data. – elembie Sep 25 '19 at 00:07
  • a.reg_ver() checks to see if a username exist on a giving forum. There is a list of forums that the username is checked against, and I want to update the page with the results as they come in. – Smitty Sep 25 '19 at 00:27

0 Answers0