39

executeAsyncScript と executeScript の違いは何ですか? window.onload などのイベントを使用するにはどうすればよいですか? 私はこのようなことを試しました

((JavascriptExecutor) driver).executeAsyncScript("window.onload = function() {alert('Hello')}"); 

しかし、もちろんうまくいきませんでした...だから、誰かがそれがどのように機能するか知っているなら、例を書いてください

4

7 に答える 7

30

(シンプルに、そして正しく保ちます。)

execteScriptとの関連する違いexecuteAsyncScriptは次のとおりです。

で呼び出される関数はexecuteAsyncScript、最後の引数として「done callback」を受け取ります。これは、スクリプトの実行が完了したことを知らせるために呼び出す必要があります。

これにより、コールバックが使用されたときにのみ「終了」するコードで使用できます。setTimeout または非同期 XHR。「完了コールバック」がタイムアウト制限内に呼び出されない場合、返された promise は拒否されます。

webdriver.WebDriver.executeAsyncScript ドキュメントによる:

#executeScript で同期 JavaScript を実行するのとは異なり、[#executeAsyncScript] で実行されるスクリプトは、提供された callback を呼び出して、終了したことを明示的に通知する必要があります。このコールバックは、実行される関数に常に最後の引数として挿入されます。

つまり、両方の関数は、完了するまでWebDriver 制御フローをブロックしexecuteScriptます。コードの最後で実行するか、名前の「async」を使用して「完了コールバック」を呼び出すと、executeAsyncScript使用される信号メカニズムを意味し、意味/暗示するものではありません。 JavaScript コードが実際に WebDriver に対して非同期で実行されること。

于 2015-11-22T19:53:45.717 に答える
26

私は使用しますexecuteScript。提供される例:

String cssSelector="...blablabla...";
JavascriptExecutor js = (JavascriptExecutor) driver;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("document.getElementById(\'"+cssSelector +"\').click();");
js.executeScript(stringBuilder.toString());

アラートの詳細に関しては、既知の問題があります。あなたはここで詳細を得ることができます

ドキュメントによると、違いは次のとおりです。

executeScript

public java.lang.Object executeScript(java.lang.String script,
                             java.lang.Object... args)

インターフェイスからコピーされた説明:JavascriptExecutor 現在選択されているフレームまたはウィンドウのコンテキストでJavaScriptを実行します。提供されたスクリプトフラグメントは、無名関数の本体として実行されます。スクリプト内で、documentを使用して現在のドキュメントを参照します。スクリプトの実行が終了すると、ローカル変数は使用できなくなりますが、グローバル変数は保持されることに注意してください。スクリプトに戻り値がある場合(つまり、スクリプトにreturnステートメントが含まれている場合)、次の手順が実行されます。

  • HTML要素の場合、このメソッドはWebElementを返します
  • 小数の場合、Doubleが返されます
  • 10進数以外の場合、Longが返されます
  • ブール値の場合、ブール値が返されます
  • 他のすべての場合、文字列が返されます。
  • 配列の場合、上記のルールに従って各オブジェクトのリストを返します。ネストされたリストをサポートします。
  • 値がnullであるか、nullが返される戻り値がない場合を除きます。

引数は、数値、ブール値、文字列、WebElement、または上記の任意の組み合わせのリストである必要があります。引数がこれらの基準を満たさない場合、例外がスローされます。引数は、関数が「Function.apply」を介して呼び出されたかのように、「arguments」マジック変数を介してJavaScriptで使用できるようになります。

指定:インターフェースJavascriptExecutorのexecuteScriptパラメーター:script-引数を実行するJavaScript-スクリプトへの引数。空の場合があります戻り値:ブール、ロング、文字列、リスト、またはWebElementのいずれか。またはnull。

executeAsyncScript

public java.lang.Object executeAsyncScript(java.lang.String script,
                                  java.lang.Object... args)

インターフェイスからコピーされた説明:JavascriptExecutor 現在選択されているフレームまたはウィンドウのコンテキストでJavaScriptの非同期部分を実行します。同期JavaScriptの実行とは異なり、このメソッドで実行されるスクリプトは、提供されたコールバックを呼び出すことによって、スクリプトが終了したことを明示的に通知する必要があります。このコールバックは、常に最後の引数として実行された関数に挿入されます。コールバック関数に渡された最初の引数は、スクリプトの結果として使用されます。この値は、同期の場合と同じ方法で処理されます。

例1:テスト対象のブラウザでスリープを実行します。

 long start = System.currentTimeMillis();
   ((JavascriptExecutor) driver).executeAsyncScript(
       "window.setTimeout(arguments[arguments.length - 1], 500);");
   System.out.println(
       "Elapsed time: " + (System.currentTimeMillis() - start));  

例2:テストをAJAXアプリケーションと同期する:

 WebElement composeButton = driver.findElement(By.id("compose-button"));
   composeButton.click();
   ((JavascriptExecutor) driver).executeAsyncScript(
       "var callback = arguments[arguments.length - 1];" +
       "mailClient.getComposeWindowWidget().onload(callback);");
   driver.switchTo().frame("composeWidget");
   driver.findElement(By.id("to")).sendKeys("bog@example.com");

例3:XMLHttpRequestを挿入し、結果を待つ:

 Object response = ((JavascriptExecutor) driver).executeAsyncScript(
       "var callback = arguments[arguments.length - 1];" +
       "var xhr = new XMLHttpRequest();" +
       "xhr.open('GET', '/resource/data.json', true);" +
       "xhr.onreadystatechange = function() {" +
       "  if (xhr.readyState == 4) {" +
       "    callback(xhr.responseText);" +
       "  }" +
       "}" +
       "xhr.send();");
   JSONObject json = new JSONObject((String) response);
   assertEquals("cheese", json.getString("food"));

スクリプト引数は、数値、ブール値、文字列、WebElement、または上記の任意の組み合わせのリストである必要があります。引数がこれらの基準を満たさない場合、例外がスローされます。引数は、「arguments」変数を介してJavaScriptで使用できるようになります。

指定:インターフェースJavascriptExecutorのexecuteAsyncScriptパラメーター:script-実行するJavaScript。args-スクリプトへの引数。空の可能性があります。戻り値:ブール、ロング、文字列、リスト、WebElement、またはnullのいずれか。

詳細なドキュメントはこちら

于 2012-11-19T12:34:01.093 に答える
9

これらの主な違いは、async で実行されるスクリプトは、提供されたコールバックを呼び出して、終了したことを明示的に通知する必要があることです。このコールバックは、常に最後の引数として実行される関数に挿入されます。

于 2014-05-30T07:57:08.520 に答える
3
((JavascriptExecutor) driver).executeScript("alert('Hello');"); 

アラートが表示されます:

((JavascriptExecutor) driver).executeAsyncScript() は、JS が Web サービス呼び出しなどで実行に時間がかかる場合に使用されます。

window.onloadページが完全に読み込まれたときに JS が実行されるようにします。

于 2012-11-19T14:55:39.563 に答える
2

私はこの機能を理解するのに多くの時間を費やし、ついに理解しました。次のコードは大いに役立ちます:

/**
 * executeAsyncScript document mentioned callback is a browser intrinsic function for returning deferred value (e.g 123 in example) from
 * js environment to Java environment
 * 
 */
@Test
public void testAsyncScript() {
    webDriver.manage().timeouts().setScriptTimeout(1, TimeUnit.SECONDS);
    Integer a = 23;
    TestUtil.elapse("first", () -> {
        Object value = getJsExecutor().executeAsyncScript("window.setTimeout(arguments[arguments.length - 1](123), 500);", a);
        // following code should be executed after 500ms timeout
        System.out.println("a is " + a); // a has nothing to do with the documented "callback"
        assertEquals(123, value);
    });

}
于 2017-03-13T14:04:33.837 に答える
0

この単純な非同期スクリプトは、DOM でクリックされた要素をリッスンし、コールバックを通じてexecuteAsyncScriptを解決します。

  var clicked_element = await driver.executeAsyncScript('var callback=arguments[arguments.length - 1]; window.document.addEventListener("click", function(e){ var element = event.srcElement ||event.target; callback(element); });'); 
于 2020-07-01T15:40:28.113 に答える