Источник события не представляет информацию для каждого клиента / сеанса - PullRequest
0 голосов
/ 03 мая 2020

У меня есть python серверная часть, которая отправляет запрос с использованием SSE.

Вот пример кода python. Он отправляет 'action-status' и данные, которые JS должен обработать (сделать):

async def sse_updates(request):
    loop = request.app.loop
    async with sse_response(request) as resp:
        while True:

            # Sending request for queue' token remove when it's been removed on server.
            if request.app['sse_requests']['update_queue_vis_remove']:
                await resp.send("update-remove")
                request.app['sse_requests']['update_queue_vis_remove'] = False

            # Sending request for queue' token adding up when it's been added on server.
            if request.app['sse_requests']['update_queue_vis_append'][0]:
                await resp.send(f"update-append {request.app['sse_requests']['update_queue_vis_append'][1]} {request.app['sse_requests']['update_queue_vis_append'][2]}")
                request.app['sse_requests']['update_queue_vis_append'][0] = False

            # Sending request for redundant token's list rewrite (on client side ofc)
            if request.app['sse_requests']['redundant_tokens_vis'][0]:
                await resp.send('update-redtokens ' + ''.join(token + ' ' for token in request.app['sse_requests']['redundant_tokens_vis'][1]))
                request.app['sse_requests']['redundant_tokens_vis'][0] = False

            await asyncio.sleep(0.1, loop=loop)
    return resp

И сценарий JS, который обрабатывает ответ:

evtSource = new EventSource("http://" + window.location.host + "/update")

evtSource.onmessage = function(e) {
    // Data from server is fetching as "<server-event-name> <data1> <data2> <data3> ..."
    let fetched_data = e.data.split(' ');

    // First option is when a token has been removed from server this event has to be represented on a client-side.
    if(fetched_data[0] === "update-remove")
        displayQueueRemove();

    // The second option is when a token appended on server and also it should be represented to a user
    else if(fetched_data[0] === "update-append")

        // fetched_data[1] - token
        // fetched_data[2] - it's (token's) position
        displayQueueAdd(fetched_data[1], parseInt(fetched_data[2]));

    // The last possible options is that if the web-page will has refreshed a data in redundant_tokens should be rewritten
    else if (fetched_data[0] === "update-redtokens"){

        fetched_data.shift();

        // Creating variables for token' wrapping
        let tag;
        let text;

        // Wrapping tokens and store it into the array.
        for(let i = 0; i < fetched_data.length - 1; i++) {
            tag = document.createElement("div");
            text = document.createTextNode(fetched_data[i]);
            tag.appendChild(text);
            tag.setAttribute("class", "token-field");
            redundant_tokens[i] = tag;
        }
    }
}

Проблема в том, что если я открою два или более браузера windows (сессий), только один из них ловит ответ и представляет его. Более того, были случаи, когда я отправлял запрос с одного сеанса, а получал ответ на другой. Есть ли возможность исправить это с помощью SSE (я имею в виду, я рассматривал некоторые другие методы, но я хотел бы попробовать с SSE)?

1 Ответ

1 голос
/ 04 мая 2020

Я думаю, что ваша проблема заключается в синхронизации данных (app["sse_requests"]).
В зависимости от того, как вы изменяете данные и кто должен быть уведомлен, вам может потребоваться вести список клиентов (сеансов).

Например, если все клиенты должны быть уведомлены обо всех событиях, сохраните list (или даже лучше set) подключенных клиентов и создайте функцию periodi c (используя create_task). в котором нужно уведомить всех из них.

Если клиенту нужно только уведомлять об определенных событиях, вам необходимо идентифицировать этого клиента, используя некоторый ключ в объекте request.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...