You could do something like this:
from flask import Flask, render_template, jsonify
app = Flask(__name__)
class Timer:
def __init__(self, current_time):
self.current_time = current_time
def decrement(self):
if self.current_time > 0:
self.current_time = self.current_time - 1
return self.current_time
t = Timer(current_time=60)
@app.route("/", methods=["GET"])
def index():
return render_template("index.html")
@app.route("/_timer", methods=["GET", "POST"])
def timer():
new_time = t.decrement()
return jsonify({"result": new_time})
if __name__ == "__main__":
app.run()
and this:
<body>
<span id="result"></span>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="{{ url_for('static', filename='jquery.js') }}">x3C/script>')</script>
<script type="text/javascript">
const root_url = {{request.root_url|tojson|safe}};
const intervalID = setInterval(update_values, 1000);
function update_values() {
$.getJSON(
root_url + "_timer",
data => {
$("#result").text(data.result);
if (data.result == 0) {
clearInterval(intervalID);
}
}
)
}
</script>
</body>
When I logged request.script_root
I got an empty string back, making the request fail, so that might also be a problem on your end. I used request.root_url
instead. request.root_url
does have a trailing slash so you need to be aware of that when you’re trying to call endpoints with it.
The idea here is to create a class where an instance of this class can be passsed an initial time which can be decremented and returned.
In your code you use both setInterval(update_values, 1000)
and time.sleep(1)
. I removed the time.sleep(1)
call since we’re already only calling the _timer
endpoint every second so we don’t need to wait an extra second.
I only decrement the time if the time is more than 0
. In the template if data.result
(i.e. the time received from Flask) is 0
we don’t decrement anymore and clear the interval.
Also be aware that since we’re decrementing the time based on setInterval
something like a refresh won’t reset the timer. That might be desired behavior, but either way something to keep in mind.