Robotic Crowd

Robotic Crowd

JavaScript内に待機時間を設定

Author: Asao Nakamura 75 views

この記事では、JavaScriptメソッドのsetTimeoutをRobotic Crowdで活用する方法を紹介します。setTimeoutメソッドではJavaScriptコードの実行途中に待機時間を設けることができます。

【できるようになること】

  • setTimeoutの使い方
  • setTimeoutを活用
ユースケース

InjectScriptでsetTimeout()やasync/awaitを利用すると、以下のようなことが可能になります。

  • InjectScriptの実行終了後もJavaScriptが実行され続ける状況を作る
  • InjectScriptのスクリプト内部に待機時間を設ける

 setTimeoutとは

setTimeoutメソッドを利用すると、JavaScriptの実行の途中に待機時間を設定することができます。

構文:setTimeout(functionName, delayTime, value1, value2...)

  • 第1引数:実行するfunction関数(必須)
  • 第2引数:待機時間(ミリ秒/任意)
  • 第3引数以降:実行するfunctionの引数に渡す値(任意)
let n = 300;
setTimeout(wait, 3000, n); //3秒後にfunction wait(n)を実行
function wait(n){ let number = n; console.log(number); }

[参考文献]

 ワークフローと平行して、バックグラウンドでJavaScriptを実行し続ける

InjectScriptでsetTimeoutを利用すると、InjectScriptの実行終了後もJavaScriptが実行され続ける状況を作ることができます。
実際のワークフローでは次のような設定を行うときに利用します。(※一例)

  • ページスクロール
  • 一部アクションの省略

ワークフローと平行して動いているJavaScriptの処理は終了する場合には次のアクションを実行します。

  • ページ遷移
  • ページのリロード
  • ワークフローの終了

例として、ワークフローの実行中に、常にページスクロールを行い続ける状態を作る場合、InejectScriptで以下のコードを事前に実行しておきます。

※ワークフローそのもののコード(YAML)は、下記ワークフロー設定内容をご参照ください。

 

[参考文献]

let scroll = function() {
  let element = document.documentElement;
  let bottom = element.scrollHeight - element.clientHeight;
  window.scroll(0, bottom);
  setTimeout(scroll, 10000); //10秒ごとにスクロールを実行
};

scroll(); //実行開始

# ブラウザを開く_Twitterプロフィール
+open_browser_1:
  action>: OpenBrowser
  url: 'https://twitter.com/maff_japan'
  lang: 'ja-JP'
  headless: true

# ページ内でJavaScriptを実行する_スクロールを実行
+inject_script_1:
  action>: InjectScript
  browser: +open_browser_1
  code: "let scroll = function() {\n  let element = document.documentElement;\n  let bottom = element.scrollHeight - element.clientHeight;\n  window.scroll(0, bottom);\n  setTimeout(scroll, 10000); //10秒ごとにスクロールを実行\n};\n\nscroll(); //実行開始\n"
  waitAfter: 10000
  returnValue: false

# 繰り返し_5回取得
+loop_1:
  loop>: 5
  _do:

    # スクリーンショットを撮る_スクロール確認
    +take_screenshot_1:
      action>: TakeScreenshot
      browser: +inject_script_1
      full_page: false
      type: png
      waitBefore: 10000

 setTimeoutが使用されたInjectScriptで値を出力する方法

setTimeoutを設定すると、InjectScriptの終了後にコードが実行されるため、returnValue(実行時の値を出力)をTRUEに設定しても、値を取得することができません。

setTimeoutを使用したInjectScript内部において、returnValueで値を受け取るためには、JavaScriptのPromise、async/awaitを利用したスクリプトを追加する必要があります。 ここでは例として、async/awaitとsetTimeoutを利用して、InjectScript内部に待機時間を設ける方法を紹介します。

スクリプト内部で待機が実行されたことを確認するため、以下の内容をreturnValueさせるスクリプトをInjectScriptに記述します。

injectScriptの開始時刻と、injectScript内部で3秒待機した後の時刻

実行結果と設定内容は、下部の「ワークフロー実行結果」をご参照ください。

スクリプト
// async関数を無名関数として即時実行します。async関数の中でのみ、指定秒の待機が可能です。
// RoboticCrowdはこのasync関数の結果を受け取ります。受け取った結果の型は、returnする値の型が保持されます(強制的にPromise型にはなりません)

(async () => {
  const startTime = new Date().toString(); //injctScriptの開始時刻

  const sleep = function(ms) {
    //msに指定したミリ秒だけ待つ関数、sleepを定義します
    return new Promise(resolve => setTimeout(resolve, ms));
  };

  await sleep(3000); //3000ミリ秒(3秒)待機します

  const endTime = new Date().toString(); //startTimeの3秒後になっています。

  return [startTime, endTime]; // 実行されるasync関数の返り値です。開始時刻、開始時刻から3秒後の時刻を返します。
})();

async/awaitはJavaScriptの中でも難しい内容の1つとされます。

「とりあえずInjectScriptのスクリプト内部に待機時間を設けたい」場合は、以下をテンプレートとしてご使用ください。
※InjectScriptのreturnValueパラメータの状態に関係なく使用可能です。

(async () => {
  const sleep = function(ms) { //msに指定したミリ秒だけ待つ関数、sleepを定義します
    return new Promise(resolve => setTimeout(resolve, ms));
  };

  // ここから処理を記述
  // 待機したいタイミングで await sleep(ミリ秒)と書けばOKです
  // 値を出力したい場合は return
})();
//InjectScript終了 この下にはユーザ定義関数以外は何も書かないでください

参考

# ブラウザを開く
+open_browser_1:
  action>: OpenBrowser
  url: 'https://www.google.com/'
  lang: 'ja-JP'
  headless: true

# ページ内でJavaScriptを実行する
+inject_script_1:
  action>: InjectScript
  browser: +open_browser_1
  code: "// async関数を無名関数として即時実行します。async関数の中でのみ、指定秒の待機が可能です。\n// RoboticCrowdはこのasync関数の結果を受け取ります。受け取った結果は、returnする値の型が保持されます(強制的にPromise型にはなりません)\n\n(async () => {\n  const startTime = new Date().toString(); //injctScriptの開始時刻\n\n  const sleep = function(ms) {\n    //msに指定したミリ秒だけ待つ関数、sleepを定義します\n    return new Promise(resolve => setTimeout(resolve, ms));\n  };\n\n  await sleep(3000); //3000ミリ秒(3秒)待機します\n\n  const endTime = new Date().toString(); //startTimeの3秒後になっています。\n\n  return [startTime, endTime]; // 実行されるasync関数の返り値です。開始時刻、開始時刻から3秒後の時刻を返します。\n})();\n"
  returnValue: true
<async/await>setTimeout/待機時間

このページは役に立ちましたか?