0

My question consists of two parts on interrupting requests:

I'm using a dynamic Java Web Application (Tomcat 8.0.15, Java EE 7 Web) with a SQL Server 2008 and JavaScript/jQuery (3.1.1).

Apparently some variants of that problem have been posted on Stackoverflow already a few years ago.

I'm having an input/textarea-field with an onkeyup-event that sends a request to a Servlet and gets a response with some kind of google-like suggestion-drop-down.

I had in my mind whenever I fire another jQuery-Ajax-Request the old on is aborted. Yesterday I realized that's not the case (any more?) and I get the dropdown several times instead of just once. If you happen to know whether or not jQuery changed something in a new version, please let me know how and if I am able to revert that.

The second part is on the server-side: I'm firing a quite heavy query to the database and would like that to be interrupted as the Ajax-Request is aborted. That seems to be quite a problem. There's a discussion here already about the same issue in PHP/MySQL (Stop mysql query when press stop button). Back in 2009 there was "no simple way": How to cancel ajax request that has run (on server side) - I wonder whether or not something changed and meanwhile I can do something about it.

There are several approaches on how the Ajax-query can be interrupted. I chose Abort Ajax requests using jQuery and my code looks like that:

Main-File:

   <html>
        <head>
            <script>
            var xhr; //global variable for the Ajax-Object
            </script>
            <meta ... />

The field is also pretty straightforward:

<textarea id="field_106" onkeyup="sendInfo(/*Some parameters*/)"></textarea>

The code:

function sendInfo(/*All the Params*/) {

//That's new
        if(xhr!=null){
            xhr.abort();
        }
//Before I haven't had that xhr-val too
        xhr=$.ajax({
            url: jsp,
            data: {
                input: document.getElementById(input).value,
                /*
                * Lots
                * of
                * other
                * parameters
                */
            },
            type: 'GET',
            success: function (result) {
                document.getElementById(output).innerHTML = result;
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                document.getElementById(output).innerHTML = "err--" + XMLHttpRequest.status + " -- " + XMLHttpRequest.statusText;
            }
        });

    }
}

Before on the Firebug-Console I had the the issue every single keyup-event is firing its own Request which results - depending on quite a few requests, depending on how much is sent: Old style of AJAX After the changes it looks like it used to: Like it should look

Apparently I'm not so wrong, Google seems to use the very same method of interrupting Requests (just their servers are faster than I can type): Google-Results

The Servlet puts together two Queries. The first four entries are the "Top Results" depending on usage, the second fetches the rest:

 private final String sql = "SELECT TOP 5 "
            // ALL THE VALS
              " FROM TopResults "
            + " WHERE Description like ? order by CNT desc";

    private final String sql2 = "SELECT  "
            // SAME VALS
            + "FROM Articles art "
            + "LEFT OUTER JOIN "
            + "TopResults ON ArtikelNr=Artikelnumber "
            + "WHERE art.Artikelbezeichnung1 like ? "
            + ""
            + "EXCEPT "
            + ""
            + sql;


    public String getInfo() {
        Connection c = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        StringBuilder ret = new StringBuilder();

        try {
            c = BaseConnection.getConnection();

            ret.append(getTableStart());

            ps = c.prepareStatement(sql);
            ps.setString(1, "%" + query + "%");
            rs = ps.executeQuery();

            ret.append(appendX("", rs));

            BaseConnection.disconnect(rs, ps);

            ps = c.prepareStatement(sql2);
            ps.setString(1, "%" + query + "%");
            ps.setString(2, "%" + query + "%");
            rs = ps.executeQuery();

            ret.append(appendX("topTR", rs));

            ret.append(getTableEnd());

            return ret.toString();
        } catch (SQLException | NamingException ex) {
            Logger.getLogger(GetInfo.class.getName()).log(Level.SEVERE, null, ex);
            return ex.getLocalizedMessage() + "<br/>" + ((ex instanceof SQLException) ? ((SQLException) ex).getSQLState() : "Naming Exception");

        } finally {
            BaseConnection.disconnect(rs, ps, c);
        }

    }

Here I was wondering about my style of sending both Statements, but it's just a style: Executing two Java PreparedStatements with one connection - style choice

I wonder if there are better methods than mine to shoot too many queries into the database. Thank you

Community
  • 1
  • 1
Qohelet
  • 1,459
  • 4
  • 24
  • 41
  • 1
    If I've understood correctly, another approach would be something called "debouncing": don't send the requests off in the first place. e.g. they start typing, but you wait until they haven't typed anything for 0.5 seconds, THEN send the request off. Unnoticable to the user, but saves you sending off all those intermediary requests while they're actually still typing. That way you don't need to cancel the requests. There are lots of javascript libraries for debouncing. – David Lavender Dec 13 '16 at 14:52
  • A pretty good approach already. @MrSpoon - I'll implement that right now – Qohelet Dec 13 '16 at 14:58
  • @MrSpoon - would you recommend to keep the xhr-abort or not? – Qohelet Dec 13 '16 at 15:11

0 Answers0