みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。
Google Apps Scriptはイベントトリガーを設定してタイマーやフォーム送信などをトリガーに自動でスクリプトを動作させることができます。
しかしそのようにイベントトリガーを設定しているスクリプトでエラーが起きたらどうなりますか?
その場合は、スクリプトは中断してしまいますよね。
今回は、以前作成したチャットワークの翻訳チャットを例にエラーが発生したかどうかを判定して、エラーによって処理を分ける方法についてお伝えします。
ちなみに、前回は記事はこちら。
翻訳したい言語のコードと文章をセミコロンでつないだメッセージを「翻訳さん」というグループチャットで送信すると、翻訳語の文章で返信が来るというシステムです。
基本的な機能はもう出来上がっているのですが、セミコロンを忘れたり、言語コードを間違えたりなど、うっかりルール外のメッセージを送ってしまうと翻訳の処理でエラーが発生して止まってしまいます。
では、行ってみましょう。
翻訳の結果が一生待っても返って来ない問題
前回作成したスクリプトはこちらでした。
function translateChat() { var token = 'APIトークン'; //チャットワークAPIトークン var room_id = XXXXXX; //翻訳さんのルームID var json = fetchMessage(token,room_id); //翻訳さんグループチャットのメッセージを取得 /* 各メッセージについて 繰り返す */ for each(var obj in json){ var arr = obj.body.split(';'); //セミコロンでsplitして配列に格納 var result = LanguageApp.translate(arr[1], "", arr[0]); //翻訳 var body = "[rp aid=" + obj.account.account_id + " to=" + room_id + "-" + obj.message_id + "] " + obj.account.name + "さん[info]翻訳結果:" + result + "[/info]"; //チャットワークに送るテキスト sendMessage(token,room_id,body); //チャットワークにメッセージを送る } }
「翻訳さん」のルールではISO639-1で登録されている言語コード(アルファベット2文字)を指定して
という形でチャットワークでメッセージを送るというのがルールです。
11行目でその本文をセミコロンで分割して
- arr[0]:言語コード
- arr[1]:本文
と格納します。
12行目でそれをもとに翻訳をするのですが、この時点でエラーが発生するとスクリプトはそこでストップをして処理が先に進まないまま終了してしまいます。
チャットワークの向こうでワクワクして待っていても、一生返事は返ってこない…ということになります。
今回はその問題を解消すべく、色々と模索をしていきたいと思います。
翻訳テスト用スクリプト
検証のために、以下のようなテスト用のスクリプトを作成してみました。
function translateTest(){ var strTest = "ja;翻訳してください"; //テスト用文字列 var arr = strTest.split(';'); //セミコロンでsplitして配列に格納 var result = LanguageApp.translate(arr[1], "", arr[0]); //翻訳 Logger.log(result); }
3行目の文字列を色々なパターンに書き換えて実行をすることで、5行目のLanguageApp.translateメソッドの挙動を確認していくためのスクリプトです。
strTestで正しい入力が与えられれば、ログ出力に翻訳結果が返ります。
例えば上記プログラムの通りstrTestが「ja;翻訳してください」であれば
このようにログ出力されます。
これを使って色々な文字列を入力してみましょう。
セミコロンがない場合
strTestにただ「翻訳してください」と入力してみます。
この場合は、「無効な引数」でエラーとなりそこで中断します。
セミコロンがないので
- arr[0]:”翻訳してください”
- arr[1]:null
となり、言語コードが不明でエラーとなります。
無効な言語コードを使った場合
strTestに存在しない言語コードzzを使って「zz:翻訳してください」としてみます。
こちらも同様に「無効な引数」エラーです。
- arr[0]:”zz”
- arr[1]:”翻訳してください”
となっていると思われますが、LanguageApp.translateメソッドではちゃんと言語コードが判定されているわけですね。
セミコロンが二つ以上ある場合
「en;翻訳してください;翻訳してください」とセミコロンを複数使った場合はどうなるでしょうか。
splitメソッドで
- arr[0]:”en”
- arr[1]:”翻訳してください”
- arr[2]:”翻訳してください”
と分割されます。arr[2]は使われることがなく、普通にLanguageApp.translateメソッドは成功するわけですね。
このパターンは特に問題ないとして良いと思います。
本文が空の場合
「en;」と本文を何も入力しない場合は
とこのように空の文字が返ってきます。
- arr[0]:”en”
- arr[1]:null
は、エラーとならないようですね。
エラーを判定して処理を分ける
LanguageApp.translateメソッドでエラーが発生するかどうかの判定はどのようにすれば良いでしょうか?
言語コードのリストをスプレッドシートに置いておいて、arr[0]の値がそこに含まれているかどうかを判定するという方法もあります。
ただし言語コードは184ありますし、他の翻訳を使うスクリプトを使う場合に毎回スプレッドシートを用意するのも…ちょっとだるいですね。
今回はLanguageApp.translateメソッドでエラーが発生するかどうかを直接キャッチしてしまう、という方法を使いたいと思います。
try~catch文を使ってエラーの発生を検知する
JavaScriptではエラーの発生をキャッチするtry~catch文というものが用意されています。
書き方はこちら。
// 処理1
}catch(e){
// 処理2
}
処理の流れを説明しますね。
まず、エラーをキャッチしたい処理をtry{ ~ }内に記載します。上記でいうと処理1の部分ですね。
処理1でエラーが起きなければ、catch(e){ ~ }内の処理2は実行されずにスルーされます。
処理1でエラーが発生した場合は、その時点で処理1を中断してcatch(e){ ~ }内の処理2が実行をされます。
ちなみに、引数eですがErrorオブジェクトつまりエラーの内容が渡されます。エラーの内容から処理を分けていきたい場合などに使えばOKです。
try~catch文を使った翻訳テスト用スクリプト
ではこのtry~catch文を使って翻訳テスト用のスクリプトを組んでみましょう。
こちらです。
function translateTest(){ var strTest = "翻訳をして下さい"; //テスト用文字列 var arr = strTest.split(';'); //セミコロンでsplitして配列に格納 try{ var result = LanguageApp.translate(arr[1], "", arr[0]); //翻訳 }catch(e){ result = "エラーの内容:" + e; } Logger.log(result); }
LanguageApp.translateメソッドが検証の対象になっていて、エラーが発生すればログにエラーの内容が出力されます。
エラーがなければ、catchの中は実行されませんので翻訳結果が出力されます。
まとめ
今回はGoogle Apps Scriptでエラーが発生したときに、try~catch文で処理を分ける方法についてお伝えしました。
次回はこの方法を用いて、チャットワークの翻訳チャットにルール外のメッセージが来たときの処理を作成していきたいと思います。
どうぞお楽しみに!