Javascript 关联数组未在服务器发送的事件环境中填充

Javascript 关联数组未在服务器发送的事件环境中填充,javascript,arrays,server-sent-events,Javascript,Arrays,Server Sent Events,我想我走错了方向: 我有一个事件源,可以为我提供有关基础系统操作的更新。该页面旨在以jquery支持的树型表显示上述事件。我完美地接受了这些事件,但我意识到有一个案例我没有处理,一个事件到达了,但却错过了它的父事件。在这种情况下,我需要从数据库中获取丢失的根节点以及该根节点所有可能丢失的子节点。这也行 //init fct //... eventSource.addEventListener("new_node", onEventSourceNewNodeEvent); //... funct

我想我走错了方向:

我有一个事件源,可以为我提供有关基础系统操作的更新。该页面旨在以jquery支持的树型表显示上述事件。我完美地接受了这些事件,但我意识到有一个案例我没有处理,一个事件到达了,但却错过了它的父事件。在这种情况下,我需要从数据库中获取丢失的根节点以及该根节点所有可能丢失的子节点。这也行

//init fct
//...
eventSource.addEventListener("new_node", onEventSourceNewNodeEvent);
//...

function onEventSourceNewNodeEvent(event) {
    let data = event.data;
    if (!data)
        return;

    let rows = $(data).filter("tr");
    rows.each(function (index, row) {
        let parentEventId = row.getAttribute("data-tt-parent-id");
        let parentNode = _table.treetable("node", parentEventId);

        // if headless state is not fully
        // resolved yet keep adding new rows to array
        if (headlessRows[parentEventId]) {
            headlessRows[parentEventId].push(row);
            return;
        } else if (parentEventId && !parentNode) { // headless state found
            if (!headlessRows[parentEventId])
                headlessRows[parentEventId] = [];

            headlessRows[parentEventId].push(row);
            fetchMissingNodes(parentEventId);
            return;
        }

        insertNode(row, parentNode);
    });
}

function fetchMissingNodes(parentEventId) {
    let url = _table.data("url") + parentEventId;

    $.get(url, function (data, textStatus, request) {
        if (!data)
            return;

        let rows = $(data).filter("tr");

        //insert root and children into table
        _table.treetable("loadBranch", null, rows);

        let parentNode = _table.treetable("node", parentEventId);
        let lastLoadedRow = $(rows.last());

        let headlessRowsArray = headlessRows[parentEventId];
        while (headlessRowsArray && headlessRowsArray.length > 0) {
            let row = headlessRowsArray.shift();
            let rowId = row.getAttribute("data-tt-id");
            if (rowId <= lastLoadedRow) // already loaded event from previous fetch
                continue;

            insertNode(row, parentNode);

            let pendingUpdatesArray = pendingUpdates[rowId];
            // shouldn't be more than one but who know future versions
            while (pendingUpdatesArray && pendingUpdatesArray.length > 0) {
                let updateEvent = headlessRowsArray.shift();
                updateNode(updateEvent)
            }
            delete pendingUpdates[rowId]; // <- something better here?
        }
        delete headlessRows[parentEventId]; // <- something better here too?

    });
}
它似乎缺少任何实际数据。然而,当我一步一步地执行它时,它显示如下:

(2957748) [empty × 2957747, Array(1)]
    2957747:[tr.node.UNDETERMINED]
    length:2957748
    __proto__:Array(0)

我遗漏了一些东西,但我仍然无法理解。

您的代码是异步的,您执行http请求,但将其视为同步代码。 试试这个办法

//初始化fct
//...
eventSource.addEventListener(“新节点”,OneEventSourceNewNodeEvent);
//...
异步函数OneEventSourceNewNodeEvent(事件){
设data=event.data;
如果(!数据)
返回;
让行=$(数据).filter(“tr”);
行。每个(函数(索引,行){
让parentEventId=row.getAttribute(“数据tt父id”);
让parentNode=_table.treetable(“节点”,parentEventId);
//如果无头状态未完全恢复
//已解决,但请继续向数组中添加新行
if(headlessRows[parentEventId]){
headlessRows[parentEventId]。推送(行);
返回;
}如果(parentEventId&!parentNode){//找到无头状态,则为else
如果(!headlessRows[parentEventId])
无标题行[parentEventId]=[];
headlessRows[parentEventId]。推送(行);
等待fetchMissingNodes(parentEventId);
返回;
}
插入节点(行,父节点);
});
}
函数fetchMissingNodes(parentEventId){
返回新承诺((解决、拒绝)=>{
让url=_table.data(“url”)+parentEventId;
$.get(url、函数(数据、文本状态、请求){
如果(!数据){
解决()
返回;
}
让行=$(数据).filter(“tr”);
//将根目录和子目录插入表中
_表.treetable(“loadBranch”,null,行);
让parentNode=_table.treetable(“节点”,parentEventId);
让lastLoadedRow=$(rows.last());
让headlessRowsArray=headlessRows[parentEventId];
while(headlessRowsArray&&headlessRowsArray.length>0){
设row=headlessRowsArray.shift();
让rowId=row.getAttribute(“数据tt id”);

如果(rowId听起来像一个竞争条件。你在填充数据之前读取数据。当你在调试器中运行它时,它有时间填充。只是猜测。但我认为JS是单线程的,因此竞争条件是不可能的。SSE会引入竞争条件的风险吗?谢谢,我不知道这个关键字。但是你把它放在了wrong spot,它需要位于
行中。每个(函数…
部分。我觉得这是正确的方向,但即使这样,问题仍然存在,我相信,正因为如此,foreach实际上是同步的。fetchMissingNodes是异步的。在fetchMissingNodes中加入承诺并在循环中执行等待将使您的循环工作同步。您尝试过运行它吗?如果我把async放在函数onEventSourceNewNodeEvent上,脚本甚至不会启动
wait只在异步函数中有效
。我将尝试把它放在两个函数声明上。我认为主要问题来自这样一个事实,即所有服务器发送的事件到达调用
onEventSourceNewNodeEvent
。如果我可以强制事件排队的话相反,我也开始认为,我的想法是使用关联数组来存储在获取根时可能到达的无头节点,这一想法存在根本性的缺陷。验证了答案,因为即使它没有解决我的特定问题(它来自对JS事件堆栈的误解),它仍然是相关的
(2957748) [empty × 2957747, Array(1)]
    2957747:[tr.node.UNDETERMINED]
    length:2957748
    __proto__:Array(0)