2016-09-16 67 views
0

我使用postMessage在JScript中调用参数给工作人员。postMessage在代码中执行得太晚

不幸的是,似乎postMessage是在DOM的主线程闲置后执行的。我需要一个函数在我的代码运行时发布。

背景:Worker正在持有一个webSocket与服务器通信。

function xy() { 
 
    flag = 0; 
 

 
    while (!flag) { 
 

 
     WORKER.postMessage(flag); 
 

 
     //Problem: WORKER does not get post; Posts are invoked after while 
 
     //Need something to break the rules 
 
     GiveWorkerExecutionTimeOrDoEventsAndMessageStack(); 
 

 
     flag := CheckFlag(); 
 
    } 
 
}

感谢您的帮助:)!

编辑:

我会尽量接近解释:

首先我有一个工人拿着一个网络插座(单独的js文件):

var wsUri = "ws://localhost:8002/chat"; 
 

 
var websocket; 
 

 
"use strict"; 
 

 
self.addEventListener('message', function (e) { 
 
    switch (e.data[0]) { 
 
     case "run": 
 
      runWebSocket(); 
 
      break; 
 
     case "send": 
 
      websocket.send(e.data[1]); 
 
      break; 
 
     case "addWait": 
 
      break; 
 
    } 
 
}, false); 
 

 
function runWebSocket() { 
 
    websocket = new WebSocket(wsUri); 
 
    websocket.binaryType = "arraybuffer"; 
 
    websocket.onopen = function (evt) { onOpen(evt) }; 
 
    websocket.onclose = function(evt) { onClose(evt) }; 
 
    websocket.onmessage = function(evt) { onMessage(evt) }; 
 
    websocket.onerror = function(evt) { onError(evt) }; 
 
} 
 

 
function onOpen(evt) { 
 
    self.postMessage(['open', '']); 
 
} 
 

 
function onClose(evt) { 
 
    self.postMessage(['close', '']); 
 
} 
 

 
function onMessage(evt) { 
 
    self.postMessage(['arrival', evt.data]); 
 
} 
 

 
function onError(evt) { 
 
    self.postMessage(['error', evt.data]); 
 
} 
 

 
function doSend(message) { 
 
    websocket.send(message); 
 
}

此Worker正在一个简单的测试环境中运行,该环境中有一个按钮和一个侦听器正在等待单击事件。

我得到我的解决方案,如果

一)发送点击数据块的完成 B)代码正在等待接收服务器的回答,请单击处理。我想发布只有在这种情况下

所以我一直在这样做的按钮点击监听按钮(见功能EventCallback):

在我创建将被存储在等待关键的开始地图。只要地图包含我的等待密钥,就不会提交点击。

发布点击内容后,我有我的等待循环。它应该等待,而我的工作人员已经发出答案,处理应该承诺。

现在我告诉你,我的问题清单:

1)即使有一个岗位的工人(点击等待循环之前的事件数据),该消息从未到达工人。工人在结束循环后得到帖子。

2)我不知道,我的检查答案从服务器会发生什么,必须发布到主线程。我开始尝试setTimeout,但如果没有帖子回到我的主线程,这是无稽之谈。

function EventCallback(evtName){WaitingKey;

evtName.stopPropagation(); 

WaitingThreadCtr++; 
WaitingKey = "#" + WaitingThreadCtr; 
WaitingThreads.set(WaitingKey, WaitingKey); 

var doc = document.implementation.createDocument(null, "controlevent", null); 

// create the <submitter>, <name>, and text node 
var submitterElement = doc.createElement("command"); 
var submitterData = doc.createElement("data"); 

Att = document.createAttribute("id"); 
Att.nodeValue = 'controlEvent'; 
submitterElement.attributes.setNamedItem(Att); 

Att = document.createAttribute("threadid"); 
Att.nodeValue = WaitingKey; 
submitterElement.attributes.setNamedItem(Att); 

for (var p in evtName) { 
    Att = document.createAttribute(p); 
    Att.nodeValue = evtName[p]; 
    submitterData.attributes.setNamedItem(Att); 
} 

submitterElement.appendChild(submitterData); 
doc.documentElement.appendChild(submitterElement); 

doSend(doc.documentElement.innerHTML); 

flag = false; 
do { 
    window.setTimeout(DoInterrupt, 100); 
    if (WaitingThreads.get(WaitingKey) != WaitingKey) flag = true; 
} while (flag == false); 

}

这只是一个简单的示例,因为我想使这个数据协议的其他地方在我的代码,以模拟功能与ByRef参数的调用。

<!DOCTYPE html> 
 
<meta charset="utf-8" /> 
 

 
<script language="javascript" type="text/javascript"> 
 

 
var wsUri = "ws://localhost:8002/chat"; 
 

 
var webSocketWorker; 
 

 
var output, outputW, outputH; 
 
var WaitingThreads; 
 
var WaitingThreadCtr; 
 
var Timer; 
 
var Interval; 
 

 
"use strict"; 
 

 
function init() { 
 
    output = document.getElementById("output"); 
 

 
    WaitingThreads = new Map(); 
 
    WaitingThreadCtr = 0; 
 

 
    webSocketWorker = new Worker("websocket.js"); 
 

 
    webSocketWorker.addEventListener('message', WebSocketServerListen, false); 
 

 
    webSocketWorker.postMessage(['run', '']); 
 
} 
 

 
function WebSocketServerListen(e) { 
 
    switch (e.data[0]) { 
 
     case 'arrival': 
 
      dataArrival(e.data[1]); 
 
      break; 
 
     case 'error': 
 
      break; 
 
     case 'open': 
 
      break; 
 
     case 'close': 
 
      break; 
 
    } 
 
} 
 

 
function doSend(message) { 
 
    webSocketWorker.postMessage(['send', message]); 
 
} 
 

 
function dataArrival(data) { 
 

 
    var i, k, m, parser, xmlDoc, NodeCommand, Tag, Att, El, id, htm, NAtt; 
 
    var DivEl, DivStyle, TagEl; 
 

 
    parser = new DOMParser(); 
 
    xmlDoc = parser.parseFromString(data, "text/xml"); 
 

 
    NodeCommand = xmlDoc.getElementsByTagName("command"); 
 

 
    //DOM ist nun verfügbar 
 
    for (i = 0; i < NodeCommand.length; i++) { 
 
     switch (NodeCommand[i].childNodes[0].textContent) { 
 
      case "event": 
 
       id = NodeCommand[i].attributes.getNamedItem("threadid").value; 
 
       WaitingThreads.delete(id); 
 
       break; 
 
      case "addControl": 
 
       //Tag einlesen; tag hat die Attribute id und html 
 
       CommandAddControl(NodeCommand[i]); 
 
       break; 
 
      case "addDiv": 
 
       //Tag einlesen; tag hat die Attribute id und html 
 
       CommandAddDiv(NodeCommand[i]); 
 
       break; 
 
      case "hideControl": 
 
       //Tag einlesen; tag hat die Attribute id und html 
 
       CommandShowHideControl(NodeCommand[i], false); 
 
       break; 
 
      case "showControl": 
 
       //Tag einlesen; tag hat die Attribute id und html 
 
       CommandShowHideControl(NodeCommand[i], true); 
 
       break; 
 
      case "resizeControl": 
 
       //Tag einlesen; tag hat die Attribute id und html 
 
       CommandResizeControl(NodeCommand[i]); 
 
       break; 
 
      case "setStyle": 
 
       //Tag einlesen; tag hat die Attribute id und html 
 
       CommandSetStyle(NodeCommand[i]); 
 
       break; 
 
      case "setProperty": 
 
       //Tag einlesen; tag hat die Attribute id und html 
 
       CommandSetProperty(NodeCommand[i]); 
 
       break; 
 
     } 
 
    } 
 
} 
 

 
function CommandAddDiv(CommandNode) { 
 
    var k, m, e, Tag, Att, El, id, htm, NAtt; 
 
    var DivEl, DivStyle, TagEl, Dest, DivDest; 
 

 
    Tag = CommandNode.getElementsByTagName("tag"); 
 

 
    for (k = 0; k < Tag.length; k++) { 
 

 
     if (Tag[k].childNodes[0]) { 
 
      El = Tag[k].childNodes[0].textContent; 
 
     } 
 

 
     id = Tag[k].attributes.getNamedItem("id").value; 
 

 
     DivEl = document.getElementById(id); 
 
     if (DivEl) DivEl.parentNode.removeChild(DivEl); 
 

 
     //div anlegen 
 
     DivEl = document.createElement("div"); 
 
     DivEl.Control = new Control(); 
 

 
     Att = document.createAttribute("id"); 
 
     Att.nodeValue = id; 
 
     DivEl.attributes.setNamedItem(Att); 
 

 
     Att = document.createAttribute("class"); 
 
     Att.nodeValue = Tag[k].attributes.getNamedItem("class").value; 
 
     DivEl.attributes.setNamedItem(Att); 
 

 
     Att = document.createAttribute("style"); 
 
     Att.nodeValue = Tag[k].attributes.getNamedItem("style").value; 
 
     DivEl.attributes.setNamedItem(Att); 
 

 
     if (Tag[k].attributes.getNamedItem("visible").value == "0") { 
 
      DivEl.style.display = "none"; 
 
     } 
 

 
     El = Tag[k].getElementsByTagName("evt"); 
 
     for (e = 0; e < El.length; e++) { 
 
      //Events binden 
 
      DivEl.addEventListener(El[e].attributes.getNamedItem("name").value, EventCallback, false); 
 
     } 
 

 
     //append to id dest 
 
     Dest = Tag[k].attributes.getNamedItem("dest").value; 
 
     if (Dest == '<root>') { 
 
      output.appendChild(DivEl); 
 
     } else { 
 
      DivDest = document.getElementById(Dest); 
 
      DivDest.appendChild(DivEl); 
 
     } 
 
    } 
 
} 
 

 
function Control() { 
 
    this.AlignLeft = 0; 
 
    this.AlignRight = 0; 
 
    this.AlignTop = 0; 
 
    this.AlignBottom = 0; 
 
} 
 

 
function CommandAddControl(CommandNode) { 
 
    var k, m, e, Tag, Att, El, id, htm, NAtt; 
 
    var DivEl, DivStyle, TagEl, Dest, DivDest; 
 

 
    Tag = CommandNode.getElementsByTagName("tag"); 
 

 
    for (k = 0; k < Tag.length; k++) { 
 

 
     if (Tag[k].childNodes[0]) { 
 
      El = Tag[k].childNodes[0].textContent; 
 
     } 
 

 
     id = Tag[k].attributes.getNamedItem("id").value; 
 

 
     DivEl = document.getElementById(id); 
 
     if (DivEl) DivEl.parentNode.removeChild(DivEl); 
 

 
     //div anlegen 
 
     DivEl = document.createElement("div"); 
 

 
     Att = document.createAttribute("id"); 
 
     Att.nodeValue = id; 
 
     DivEl.attributes.setNamedItem(Att); 
 

 
     Att = document.createAttribute("style"); 
 
     Att.nodeValue = Tag[k].attributes.getNamedItem("style").value; 
 
     DivEl.attributes.setNamedItem(Att); 
 

 
     TagEl = document.createElement(El); 
 
     TagEl.textContent = Tag[k].attributes.getNamedItem("html").value; 
 

 
     //Tag-Node kann Att-Knoten haben 
 
     NAtt = Tag[k].getElementsByTagName("att"); 
 

 
     for (m = 0; m < NAtt.length; m++) { 
 
      Att = document.createAttribute(NAtt[m].attributes.getNamedItem("name").value); 
 
      Att.nodeValue = NAtt[m].attributes.getNamedItem("value").value; 
 
      TagEl.attributes.setNamedItem(Att); 
 
     } 
 
     DivEl.appendChild(TagEl); 
 

 
     //Events binden 
 
     El = Tag[k].getElementsByTagName("evt"); 
 
     for (e = 0; e < El.length; e++) { 
 
      //Events binden 
 
      TagEl.addEventListener(El[e].attributes.getNamedItem("name").value, EventCallback, false); 
 
     } 
 

 
     //append to id dest 
 
     Dest = Tag[k].attributes.getNamedItem("dest").value; 
 
     if (Dest == '<root>') { 
 
      output.appendChild(DivEl); 
 
     } else { 
 
      DivDest = document.getElementById(Dest); 
 
      DivDest.appendChild(DivEl); 
 
     } 
 
    } 
 
} 
 

 
function CommandShowHideControl(CommandNode, ShowHide) { 
 
    var k, m, Tag, Att, El, id, htm, NAtt; 
 
    var DivEl, DivStyle, TagEl, Dest, DivDest; 
 

 
    Tag = CommandNode.getElementsByTagName("tag"); 
 

 
    for (k = 0; k < Tag.length; k++) { 
 
     id = Tag[k].attributes.getNamedItem("id").value; 
 

 
     El = document.getElementById(id); 
 
     if (El) { 
 
      if (ShowHide == false) { 
 
       El.style.display = "none"; 
 
      } else { 
 
       El.style.display = "block"; 
 
      } 
 
     } 
 
    } 
 
} 
 

 
function CommandResizeControl(CommandNode) { 
 
    var k, m, Tag, Att, El, id, htm, NAtt; 
 
    var DivEl, DivStyle, TagEl, Dest, DivDest; 
 

 
    Tag = CommandNode.getElementsByTagName("tag"); 
 

 
    for (k = 0; k < Tag.length; k++) { 
 
     id = Tag[k].attributes.getNamedItem("id").value; 
 

 
     El = document.getElementById(id); 
 
     if (El) { 
 
      El.style.left = Tag[k].attributes.getNamedItem("left").value; 
 
      El.style.top = Tag[k].attributes.getNamedItem("top").value; 
 
      El.style.width = Tag[k].attributes.getNamedItem("width").value; 
 
      El.style.height = Tag[k].attributes.getNamedItem("height").value; 
 
     } 
 
    } 
 
} 
 

 
function CommandSetStyle(CommandNode) { 
 
    var k, m, Tag, Att, El, id, htm, NAtt; 
 
    var DivEl, DivStyle, TagEl, Dest, DivDest; 
 

 
    Tag = CommandNode.getElementsByTagName("tag"); 
 

 
    for (k = 0; k < Tag.length; k++) { 
 
     id = Tag[k].attributes.getNamedItem("id").value; 
 

 
     El = document.getElementById(id); 
 
     if (El) { 
 
      El.style = Tag[k].attributes.getNamedItem("style").value; 
 
     } 
 
    } 
 
} 
 

 
function CommandSetProperty(CommandNode) { 
 
    var k, m, Tag, Att, El, id, htm, NAtt; 
 
    var DivEl, DivStyle, TagEl, Dest, DivDest; 
 

 
    Tag = CommandNode.getElementsByTagName("tag"); 
 

 
    for (k = 0; k < Tag.length; k++) { 
 
     id = Tag[k].attributes.getNamedItem("id").value; 
 

 
     El = document.getElementById(id); 
 
     if (El) { 
 
      eval("El." + Tag[k].attributes.getNamedItem("property").value + " = " + Tag[k].attributes.getNamedItem("value").value); 
 
     } 
 
    } 
 
} 
 

 
function TimeoutFunc() { 
 
    //Timer = setTimeout(TimeoutFunc, 50); 
 
} 
 

 
function WaitInterval() { 
 
    Timer = setTimeout(TimeoutFunc, 10); 
 
} 
 

 
function EventCallback(evtName) { 
 
    var WaitingKey; 
 

 
    evtName.stopPropagation(); 
 

 
    WaitingThreadCtr++; 
 
    WaitingKey = "#" + WaitingThreadCtr; 
 
    WaitingThreads.set(WaitingKey, WaitingKey); 
 

 
    var doc = document.implementation.createDocument(null, "controlevent", null); 
 

 
    // create the <submitter>, <name>, and text node 
 
    var submitterElement = doc.createElement("command"); 
 
    var submitterData = doc.createElement("data"); 
 

 
    Att = document.createAttribute("id"); 
 
    Att.nodeValue = 'controlEvent'; 
 
    submitterElement.attributes.setNamedItem(Att); 
 

 
    Att = document.createAttribute("threadid"); 
 
    Att.nodeValue = WaitingKey; 
 
    submitterElement.attributes.setNamedItem(Att); 
 

 
    for (var p in evtName) { 
 
     Att = document.createAttribute(p); 
 
     Att.nodeValue = evtName[p]; 
 
     submitterData.attributes.setNamedItem(Att); 
 
    } 
 

 
    submitterElement.appendChild(submitterData); 
 
    doc.documentElement.appendChild(submitterElement); 
 

 
    doSend(doc.documentElement.innerHTML); 
 
    
 
    flag = false; 
 
    do { 
 
     window.setTimeout(DoInterrupt, 100); 
 
     if (WaitingThreads.get(WaitingKey) != WaitingKey) flag = true; 
 
    } while (flag == false); 
 
} 
 

 
function DoInterrupt() { 
 
    
 
} 
 

 
function WindowResize(evtName) { 
 
    var w, h; 
 
    w = output.clientWidth; 
 
    h = output.clientHeight; 
 
    
 
    if ((outputW != w) || (outputH != h)) { 
 

 
     outputW = w; 
 
     outputH = h; 
 

 
     var Att; 
 
     var doc = document.implementation.createDocument(null, "windowResize", null); 
 

 
     // create the <submitter>, <name>, and text node 
 
     var submitterElement = doc.createElement("command"); 
 
     Att = document.createAttribute("id"); 
 
     Att.nodeValue = 'windowResize'; 
 
     submitterElement.attributes.setNamedItem(Att); 
 

 
     Att = document.createAttribute("width"); 
 
     Att.nodeValue = w; 
 
     submitterElement.attributes.setNamedItem(Att); 
 

 
     Att = document.createAttribute("height"); 
 
     Att.nodeValue = h; 
 
     submitterElement.attributes.setNamedItem(Att); 
 

 
     doc.documentElement.appendChild(submitterElement); 
 

 
     doSend(doc.documentElement.innerHTML); 
 

 
    } 
 
} 
 

 
function writeToScreen(message) { 
 
    var pre = document.createElement("p"); 
 
    pre.style.wordWrap = "break-word"; 
 
    pre.innerHTML = message; 
 
    output.appendChild(pre); 
 
} 
 

 
window.addEventListener("load", init, false); 
 
window.addEventListener("resize", WindowResize, false); 
 

 
</script> 
 

 
<link rel="stylesheet" href="w3.css"> 
 
<html> 
 

 
<head> 
 
<title>WebSocket Test</title> 
 
</head> 
 

 
<body> 
 
<h2>WebSocket Test</h2> 
 

 
<div id="output"></div> 
 

 
</body> 
 
</html>

+0

你可以提供一些更多的信息和你是如何在主线程 –

+0

接收消息我可以告诉你的是这将工作在正常的JavaScript。我刚刚测试过... –

回答

0

正如我一直工作在多线程JS API(OODK-JS)我可以回答这个问题:

是不可能打破与异步调用一个无限循环(包括setTimout ),因为回调函数只在线程免费时执行。运行一个无限循环垄断线程和所有异步回调被延迟,直到循环完成,从来没有发生

flag = false; 
do { 
    // DoInterrupt is never called as the do/while loop is monopolizing the current thread 
    window.setTimeout(DoInterrupt, 100); 
    if (WaitingThreads.get(WaitingKey) != WaitingKey) flag = true; 
} while (flag == false);