使用 Flask 轮询 API 并在返回的数据发生变化时更新网页

Polling an API with Flask and updating webpage if returned data has changed

我正在构建一个自定义的 Spotify 音乐播放器,在后端使用 Flask 来处理对 Spotify 的调用 API。它从当前播放的曲目中获取信息并填充本地网页。我现在需要轮询 Spotify API(每 2 秒左右)以检查歌曲是否已更改,如果已更改,请更新网页(希望使用 JavaScript,这样就无需刷新页面).我不确定如何用 Flask 做到这一点,或者是否有更好的方法来解决这个问题。我相信我可以通过创建和调用一个异步函数来进行轮询来解决这个问题,但是如果发现有变化,我不确定从那里去哪里。

这是我到目前为止的 spotify 视图。我在 spotify.py 文件中的自定义身份验证和 now_playing 函数中使用 spotipy 库。

@app.route('/spotify')
def spotify():

    # Get Spotify instance and authorization token
    authData = dev.auth()
    sp = authData[0]
    token = authData[1]

    current = dev.now_playing(sp, token)

    # Assign individual track information to variable for sending to web page via Jinja
    separator = ', '
    return render_template('spotify.html', 
        artists = separator.join(current[0]),
        song = current[1],
        album = current[2],
        cover_url = current[3],
        year = current[4],
        auth_tok = token
    )

本人web开发经验有限,第一次使用Flask。我正在使用这个项目来了解更多信息,但遇到了这个障碍。

概念

轮询 APIs 的一种好方法是在 javascript 中安排请求,然后等待一定时间(不超过 10-30 秒)让服务器保留请求看看歌曲是否改变然后 return 结果。如果发现结果早于 10-30 秒,服务器会提前 return 发送它。客户端将请求视为正在进行中,并且只要请求没有超时(超过 30+ 秒左右),服务器就可以在整个 window 中接收它。您也可以每隔几秒简单地请求 url 进行检查,但这会占用大量系统资源。

API代码

from flask import Flask, redirect
song = "" # global identifier
@app.route("/track", methods=["GET"])
def track():
    for _ in range(10):
        time.sleep(1)
        global song # regrab the song value every iteration
        current = dev.now_playing(sp, token) # get current song
        if current[1] != song: # song changed
            song = current[1]
            return redirect("http://www.website.com/spotify", code=302) #essentially an automatic refresh by redirecting to itself, and will regrab the song data!
    return {}, 200 # give the client SOMETHING so the request doesn't timeout and error

@app.route('/spotify')
def spotify():
    global song
    # Get Spotify instance and authorization token
    authData = dev.auth()
    sp = authData[0]
    token = authData[1]
    current = dev.now_playing(sp, token)
    # Assign individual track information to variable for sending to web page via Jinja
    separator = ', '
    song = "" # assign the song value to whatever is sent to the client
    return render_template('spotify.html', 
        artists = separator.join(current[0]),
        song = current[1],
        album = current[2],
        cover_url = current[3],
        year = current[4],
        auth_tok = token
    )

提供的代码将接受来自客户端的请求,然后检查客户端上次刷新页面时代表歌曲的值 global song 是否与当前歌曲 API 不同正在使用。在这种情况下,服务器将发送一个重定向代码,这样客户端将重定向并基本上刷新它所在的当前页面,从而获取歌曲和信息!

Javascript

javascript代码将使用简单的请求,并使用 GET 不断获取端点 /track 上的服务器数据。可以找到 here 或自己研究 javascript 获取请求。要连续发出请求,请使用以下代码。

function stopFunction(){
        clearInterval(myVar); // stop the timer
    }
    $(document).ready(function(){
        myVar = setInterval("makeRequest()", 1000);
    });

这不是我提供的可扩展代码段,但应该适用于私有访问,并且可以在概念上适应为可扩展端点。