如何从 Python 调用 Javascript 函数
How to call a Javascript function from Python
我有一个不与客户端交互的 python 代码(服务器端)。但是,我需要在它(服务器代码)完成时表示一些项目。我想到的唯一想法是表示一个项目的 JS 函数,从 Python 调用。你能告诉我软件包或其他实现这个的想法吗?
一些细节(我不知道是否有必要,但可能会有帮助)
async def start_delete_delay(app, delay):
"""
The very function which thrust a delay for each front token.
Key arguments:
app -- our application.
delay -- a delay in seconds
"""
async with app['db'].acquire() as conn:
# First of all we need to check for database emptiness
query = text("SELECT True FROM tokens LIMIT(1)")
if await conn.fetch(query):
# If database is not empty then we are processing a waiting delay.
# First, fetching an id & related token from the first position (due to it queue) from database.
query = select([db.tokens.c.id, db.tokens.c.token]).order_by(asc(db.tokens.c.id)).limit(1)
query_result = await conn.fetchrow(query)
# Retrieving an id and token
id_before_sleep, token = query_result['id'], query_result['token']
# Setting a delay
try:
await asyncio.sleep(delay)
# Some information related with cancellation error
# https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel
except asyncio.CancelledError:
pass
# Check whether a token at the first place as same as it was before
finally:
# If it possible but all of members picked their tokens over 60 seconds.
if await conn.fetch(text("SELECT True FROM tokens LIMIT(1)")):
query_result = await conn.fetchrow(query)
id_after_sleep = query_result['id']
# If they are same then we delete that token and starting delay again.
if id_before_sleep == id_after_sleep:
query = delete(db.tokens).where(db.tokens.c.id == id_before_sleep)
# preparing a token for reuse.
app['new_token'].prepare_used_token(token)
# Deleting a token
await conn.fetchrow(query)
# I'd like to call a JS function (which I already have) here
# Starting a delay for adjacent token, over and over and over
task = make_task(start_delete_delay, app, delay)
asyncio.gather(task)
我找到了两个解决方案,所以如果有人遇到此类问题,请尝试使用它们:
第一个解决方案
线索是 WebSockets。我使用了 aiohttp
和 asyncio
.
在JavaScript文件中我添加了一个监听套接字:
var socket = new WebSocket('/link-to-websocket')
在服务器端,我添加了一个 websocket_handler,在我的例子中,它在从数据库中删除令牌后发送消息
async def websocket_handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
if app['updt_flag']:
await ws.send_str("signal")
else:
await ws.close()
return ws
并将其添加到路线
app.add_routes([web.get('/link-to-websocket', websocket_handler)])
1) How JavaScript works: Deep dive into WebSockets and HTTP/2 with SSE + how to pick the right path
但是这种方法不是最好的,我们不会使用整个 websocket 的功能,因此让我们继续使用另一种方法:服务器发送事件 (SSE)。这种方法更适合我的问题,因为我们总是在没有请求的情况下从服务器接收响应(而 websockets 不包含这样的选项):
第二种解法
正如我上面所说,我将使用 SSE 并且出于这些目的,它需要一个 sse-package
pip install aiohttp_sse
import asyncio
from aiohttp_sse import sse_response
async def SSE_request(request):
loop = request.app.loop
async with sse_response(request) as resp:
while True:
if request.app['updt_flag']:
await resp.send("signal")
request.app['updt_flag'] = False
await asyncio.sleep(1, loop=loop)
return resp
添加路线
web.get('/update', SSE_request)
给JS添加监听sse:
const evtSource = new EventSource("/update");
evtSource.onmessage = function(e) {
display_queue_remove();
}
就这些:)
我有一个不与客户端交互的 python 代码(服务器端)。但是,我需要在它(服务器代码)完成时表示一些项目。我想到的唯一想法是表示一个项目的 JS 函数,从 Python 调用。你能告诉我软件包或其他实现这个的想法吗?
一些细节(我不知道是否有必要,但可能会有帮助)
async def start_delete_delay(app, delay):
"""
The very function which thrust a delay for each front token.
Key arguments:
app -- our application.
delay -- a delay in seconds
"""
async with app['db'].acquire() as conn:
# First of all we need to check for database emptiness
query = text("SELECT True FROM tokens LIMIT(1)")
if await conn.fetch(query):
# If database is not empty then we are processing a waiting delay.
# First, fetching an id & related token from the first position (due to it queue) from database.
query = select([db.tokens.c.id, db.tokens.c.token]).order_by(asc(db.tokens.c.id)).limit(1)
query_result = await conn.fetchrow(query)
# Retrieving an id and token
id_before_sleep, token = query_result['id'], query_result['token']
# Setting a delay
try:
await asyncio.sleep(delay)
# Some information related with cancellation error
# https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel
except asyncio.CancelledError:
pass
# Check whether a token at the first place as same as it was before
finally:
# If it possible but all of members picked their tokens over 60 seconds.
if await conn.fetch(text("SELECT True FROM tokens LIMIT(1)")):
query_result = await conn.fetchrow(query)
id_after_sleep = query_result['id']
# If they are same then we delete that token and starting delay again.
if id_before_sleep == id_after_sleep:
query = delete(db.tokens).where(db.tokens.c.id == id_before_sleep)
# preparing a token for reuse.
app['new_token'].prepare_used_token(token)
# Deleting a token
await conn.fetchrow(query)
# I'd like to call a JS function (which I already have) here
# Starting a delay for adjacent token, over and over and over
task = make_task(start_delete_delay, app, delay)
asyncio.gather(task)
我找到了两个解决方案,所以如果有人遇到此类问题,请尝试使用它们:
第一个解决方案
线索是 WebSockets。我使用了 aiohttp
和 asyncio
.
在JavaScript文件中我添加了一个监听套接字:
var socket = new WebSocket('/link-to-websocket')
在服务器端,我添加了一个 websocket_handler,在我的例子中,它在从数据库中删除令牌后发送消息
async def websocket_handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
if app['updt_flag']:
await ws.send_str("signal")
else:
await ws.close()
return ws
并将其添加到路线
app.add_routes([web.get('/link-to-websocket', websocket_handler)])
1) How JavaScript works: Deep dive into WebSockets and HTTP/2 with SSE + how to pick the right path
但是这种方法不是最好的,我们不会使用整个 websocket 的功能,因此让我们继续使用另一种方法:服务器发送事件 (SSE)。这种方法更适合我的问题,因为我们总是在没有请求的情况下从服务器接收响应(而 websockets 不包含这样的选项):
第二种解法 正如我上面所说,我将使用 SSE 并且出于这些目的,它需要一个 sse-package
pip install aiohttp_sse
import asyncio
from aiohttp_sse import sse_response
async def SSE_request(request):
loop = request.app.loop
async with sse_response(request) as resp:
while True:
if request.app['updt_flag']:
await resp.send("signal")
request.app['updt_flag'] = False
await asyncio.sleep(1, loop=loop)
return resp
添加路线
web.get('/update', SSE_request)
给JS添加监听sse:
const evtSource = new EventSource("/update");
evtSource.onmessage = function(e) {
display_queue_remove();
}
就这些:)