<アプリケーション間の通信は非同期>

 

以下のスクリプトは、BridgeTalkを使ってInDesignからPhotoshopにスクリプトを送信するものです。

もし、Photoshopの作業終了を待っている(同期している)のなら、先にPhotoshopで「opened」のアラートが表示され、その後、InDesignで「fin」のアラートが表示されるはずです。

//InDesignで選択されているリンク画像をPhotoshopで開く(同期、非同期の検証)
#target 'indesign'
//Photoshopで実行する関数 function openPsd(fPath) { var fileObj = new File(fPath); app.open ( fileObj ); $.sleep (2000); alert ( "opened" ); } //-------------------------------------- // InDesignで実行される部分 //-------------------------------------- var selObj = app.selection[0].allGraphics[0]; //選択したオブジェクトから... var filePath = selObj.itemLink.filePath; //ファイルパスを取得 //BrideTalk var btObj = new BridgeTalk(); //BridgeTalkオブジェクト作成 btObj.target = 'photoshop'; //送信先 btObj.body = uneval ( openPsd )+"("+uneval(filePath)+")"; //Photoshopで実行させる命令 btObj.send(); //送信 alert ( "fin" );

しかし、結果は「fin」が先に表示され、「opened」が後に表示されるはずです。InDesignで実行されているスクリプトは、BridgeTalkでPhotoshopへスクリプトを送信した後、送信先のスクリプトとは非同期的に実行されているということが確認できます。

 

送信するだけで完了する処理であれば、非同期であることは問題になりません。しかし、送信先アプリケーションの作業完了を待ってから次の作業に移りたい場合、「同期をとる仕組み」が必要なことがわかります。

そのような目的のために、BridgeTalkオブジェクトにはonResultというプロパティが用意されています。送信先のスクリプトが終了する、もしくはスクリプトのどこかでreturrnが返されると、このプロパティに設定された処理が呼び出される仕組みになっています。

このように送信先から送信元へ通信する仕組みを「コールバック」といいます。

 

<コールバックの失敗例>

 

onResultによるコールバックを成功させる前に、2つの失敗例でその仕組みを検証してみます。

//InDesignで選択されているリンク画像をPhotoshopで開く(コールバックの失敗 1)
#target 'indesign'
//Photoshopで実行する関数 function openPsd(fPath) { var fileObj= new File(fPath); app.open ( fileObj ); $.sleep (2000); alert ( "opened" ); } //-------------------------------------- // InDesignで実行される部分 //-------------------------------------- var selObj= app.selection[0].allGraphics[0]; //選択したオブジェクトから... var filePath= selObj.itemLink.filePath; //ファイルパスを取得 //BrideTalk var btObj= new BridgeTalk(); //BridgeTalkオブジェクト作成 btObj.target= 'photoshop'; //送信先 btObj.body= uneval ( openPsd )+"("+uneval(filePath)+")"; //Photoshopで実行させる命令 btObj.onResult= alert ( "fin" ); //<-- コールバックされる予定 btObj.send(); //送信
alert ( "end of line" );

 

上の例では期待した結果にはならず、「fin」が先に表示され、次に「end of line」、そして最後に「opened」が表示されます。

「end of line」よりも「fin」のほうが先に表示されるということから、onResultは常に送信先の呼び出しを待っているわけではなく、待つ必要のない処理はすかさず実行されてしまうことがわかります(JavaScriptの性質上そうなってしまう)。

 

その性質を踏まえて、即実行されないためにonResultでの処理を関数化したのが以下の例です。関数であれば必要になったとき(呼び出されたとき)に処理されるはずです。

//InDesignで選択されているリンク画像をPhotoshopで開く(コールバックの失敗 2)
#target 'indesign'
//Photoshopで実行する関数 function openPsd(fPath) { var fileObj = new File(fPath); app.open ( fileObj ); $.sleep (2000); alert ( "opened" ); } //-------------------------------------- // InDesignで実行される部分 //-------------------------------------- var selObj= app.selection[0].allGraphics[0]; //選択したオブジェクトから... var filePath= selObj.itemLink.filePath; //ファイルパスを取得 //BrideTalk var btObj= new BridgeTalk(); //BridgeTalkオブジェクト作成 btObj.target= 'photoshop'; //送信先 btObj.body= uneval ( openPsd )+"("+uneval(filePath)+")"; //Photoshopで実行させる命令 btObj.onResult= function(){ alert ( "fin" ); } //<-- コールバック処理を関数化した btObj.send(); //送信 alert ( "end of line" );

 

ところが、これでも期待通りの結果にはなりません。上記の場合は最初に「end of line」、次に「opened」が表示され、「fin」は表示されません。onResultによって関数が呼び出される準備はしたものの、「呼び出されるまで待つ環境がない」からです。

具体的にいえば、onResultへ設定された処理はどこかにスタックされて待ち受けているわけではなく、送信先からのコールバックは稼働しているスクリプト(送信元)へ戻るようになっています。つまり、コールバックされたときに、送信元のスクリプトは稼働し続けていなければならないということです。

 

そういった環境を提供するのが次に述べる「#targetengine」という仕組みです。

 

<コールバックを待つ環境を用意する>

 

通常のスクリプトは、自らの処理が終われば暗示的に消滅します。

しかし、今回のようにBridgeTalkからのコールバックを待ち受ける場合、スクリプトが消滅せずにアイドル状態で常駐していなければならなりません。

 

そういった場合に用意されているのがtargetengineという仕組みです。これによってスクリプトは自分の居場所を確保し、そこで常駐することが可能になります。

 

最後の失敗例は、冒頭に1行加えただけで期待通りに動作します。

//InDesignで選択されているリンク画像をPhotoshopで開く(コールバック成功)
#target 'indesign'
#targetengine 'nakatojiTest' //<-- 加えた1行
//Photoshopで実行する関数 function openPsd(fPath) { var fileObj = new File(fPath); app.open ( fileObj ); $.sleep (2000); alert ( "opened" ); } //-------------------------------------- // InDesignで実行される部分 //-------------------------------------- var selObj= app.selection[0].allGraphics[0]; //選択したオブジェクトから... var filePath= selObj.itemLink.filePath; //ファイルパスを取得 //BrideTalk var btObj= new BridgeTalk(); //BridgeTalkオブジェクト作成 btObj.target= 'photoshop'; //送信先 btObj.body= uneval ( openPsd )+"("+uneval(filePath)+")"; //Photoshopで実行させる命令 btObj.onResult= function(){ alert ( "fin" ); } //<-- コールバック処理 btObj.send(); //送信 alert ( "end of line" );

 

なお、#targetengineのコーテーション内は基本的にスクリプト固有の名前にしなければなりません。そうしないと非常に危険な状態を招くことになります(参照:targetengineについて)。

 

 

Joomla templates by a4joomla