自己的线程中的Selenium异步脚本会阻止其他脚本

时间:2022-12-06 09:07:05

I have this scenario:

我有这种情况:

Different scripts have to be executed within the browser. On of them is to send a message from one browser to another (WebRTC). I want to measure the delay of each operation, sending messages in particular.

必须在浏览器中执行不同的脚本。他们就是从一个浏览器向另一个浏览器发送消息(WebRTC)。我想测量每个操作的延迟,特别是发送消息。

To achieve that I have created an own thread for each selenium driver, which is executing the scripts. Furthermore I have created another thread that is waiting for messages to arrive at the observed browser from other browsers. The thread which waits for the messages executes an asynchronous script like this:

为了实现这一点,我为每个执行脚本的selenium驱动程序创建了一个自己的线程。此外,我创建了另一个线程,等待消息从其他浏览器到达观察到的浏览器。等待消息的线程执行如下的异步脚本:

String message = (String) ((JavascriptExecutor) driver).executeAsyncScript(
 "window.receivedMessage = function(message_id){" +
                                  "arguments[arguments.length - 1](message_id);" +
                           "}");

As you see I am waiting for a callback that is called, if a browser receives a message.

如您所见,我正在等待调用的回调,如果浏览器收到消息。

Unfortunatelly, this blocks every other script I want to be executed after this async script is registered in the browser (doesn't matter if .executeScript() or .executeAsyncScript() ).

不幸的是,在浏览器中注册异步脚本之后,这会阻止我想要执行的所有其他脚本(无论是.executeScript()还是.executeAsyncScript())都无关紧要。

Does someoe have an idea how to constantly waiting for messages to arrive AND execute other script with a webdriver?

someoe是否知道如何不断等待消息到达并使用webdriver执行其他脚本?

EDIT

By the way: busy waiting shouldn't be the solution. I would prefer a way to notify selenium somehow that an operation is done, without constantly polling the result from the driver.

顺便说一句:忙碌的等待不应该是解决方案。我更喜欢以某种方式通知selenium操作已完成,而不会不断地轮询驱动程序的结果。

1 个解决方案

#1


0  

One way would be to store the messages in a global variable and handle them once the other scripts are executed. Here is an example:

一种方法是将消息存储在全局变量中,并在执行其他脚本后处理它们。这是一个例子:

JavascriptExecutor js = (JavascriptExecutor)driver;
driver.manage().timeouts().setScriptTimeout(20, TimeUnit.SECONDS);

// set a listener for the messages
js.executeScript(
    "window._asyncResult = [];                        " +
    "window.receivedMessage = function(message_id) {  " +
    "  window._asyncResult.push(message_id);          " +
    "};                                               " );

// send a message asynchroniously every second
js.executeScript(
    "window._asyncTimer = setInterval(function(){     " +
    "  window.receivedMessage(Math.random());         " +
    "}, 1000);                                        " );

// wait for 5 messages and return the list
List messages = (ArrayList)js.executeAsyncScript(
    "var callback = arguments[arguments.length - 1];  " +
    "(function fn(){                                  " +
    "  if(window._asyncResult.length > 5) {           " +
    "    clearInterval(window._asyncTimer);           " +
    "    return callback(window._asyncResult);        " +
    "  }                                              " +
    "  setTimeout(fn, 30);                            " +
    "})();                                            " );

#1


0  

One way would be to store the messages in a global variable and handle them once the other scripts are executed. Here is an example:

一种方法是将消息存储在全局变量中,并在执行其他脚本后处理它们。这是一个例子:

JavascriptExecutor js = (JavascriptExecutor)driver;
driver.manage().timeouts().setScriptTimeout(20, TimeUnit.SECONDS);

// set a listener for the messages
js.executeScript(
    "window._asyncResult = [];                        " +
    "window.receivedMessage = function(message_id) {  " +
    "  window._asyncResult.push(message_id);          " +
    "};                                               " );

// send a message asynchroniously every second
js.executeScript(
    "window._asyncTimer = setInterval(function(){     " +
    "  window.receivedMessage(Math.random());         " +
    "}, 1000);                                        " );

// wait for 5 messages and return the list
List messages = (ArrayList)js.executeAsyncScript(
    "var callback = arguments[arguments.length - 1];  " +
    "(function fn(){                                  " +
    "  if(window._asyncResult.length > 5) {           " +
    "    clearInterval(window._asyncTimer);           " +
    "    return callback(window._asyncResult);        " +
    "  }                                              " +
    "  setTimeout(fn, 30);                            " +
    "})();                                            " );