如果返回的数据已更改,则使用 Flask 轮询 API 并更新网页

Posted

技术标签:

【中文标题】如果返回的数据已更改,则使用 Flask 轮询 API 并更新网页【英文标题】:Polling an API with Flask and updating webpage if returned data has changed 【发布时间】:2022-01-20 20:25:09 【问题描述】:

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

这是我到目前为止的 spotify 视图。我在 spotify.py 文件中的自定义 auth 和 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。我正在使用这个项目来了解更多信息,但遇到了这个障碍。

【问题讨论】:

【参考方案1】:

概念

轮询 API 的一种好方法是在 javascript 中安排请求,然后等待一定时间(不超过 10-30 秒)让服务器保留请求以查看歌曲是否更改,然后返回结果。如果发现结果早于 10-30 秒,则服务器会提前返回。客户端将请求视为正在进行中,并且可以在服务器拥有它的整个窗口中接收它,只要请求不超时(超过 30+ 秒左右)。您也可以每隔几秒钟简单地请求一次 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 get 请求。要连续发出请求,请使用以下代码。

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

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

【讨论】:

这似乎正是我所需要的,谢谢。我现在几乎在歌曲更改后立即看到正确的重定向响应。我现在遇到的问题实际上是使用新歌曲数据更新网页,因为来自 /poll 的重定向实际上并没有刷新页面。我认为最好的方法是将新歌曲数据从 Flask 发送到 JS 文件,并使用 AJAX 更新专辑封面 url、歌曲标题等。我不确定如何将所需的数据添加到响应中并从那里更改页面。 您可以像您提到的那样将所有数据作为 json 对象重新发送,然后执行 document.innerHtml 并将现有元素更改为新值。我建议不要发送整个模板,因为那样 URL 会完全改变,但页面看起来还是一样的,而且不好。我会看看我是否可以找出重定向,然后如果可以的话编辑我的回复。很高兴为您提供帮助,祝您有美好的一天!

以上是关于如果返回的数据已更改,则使用 Flask 轮询 API 并更新网页的主要内容,如果未能解决你的问题,请参考以下文章

Flask框架:如何运用Ajax轮询动态绘图

Flask框架:运用Ajax轮询动态绘图

flask 轮询

在 Perl 中,如何在没有轮询但有超时的情况下监视文件更改?

如果从已保存在数据库(领域)中更改,则观察 JSON 响应

无需轮询即可检测 PHP 中的文件更改