11 Replies Latest reply on Nov 30, 2009 7:47 AM by pvisell

    Removing $Sleep in code

    pvisell

      Hi,

       

      I had a previous post that was answered.  The code that was given had a few sleep commands in there. I was happy for it to run on my machine but I had to put in a big value sleep(10000) for my indesign document and illustrator script to both update and refresh correctly.

       

      When I was demonstrating this via remote desktop things got a bit slow and the gragh did not refresh on the Indesign.  Therefore I had to run the code twice.  Sometimes it is the graph that does not update the dataset and therefore contains the values from the previous variables file.  Other times it's just that the graph has not completed saving properly and therefore when Indesign refreshes it still picks up the old graph.  This will be a real problem for us when the code goes live.  Basically, I want to know if anyone can re-write the below so that no sleep commands are run.

       

      Basically the script is called from within Indesign. It opens up the Graph in illustrator.  Loads the variable file and updates the dataset.  It then saves the file and closes it.  Back in Indesign, all links are then refreshed.  Any help would be appreciated.  Thanks.

        • 1. Re: Removing $Sleep in code
          pvisell Level 1

          Code below....thanks

           

          #target indesign


          function main() {

          if (app.documents.length == 0) {

          alert("Please have an 'Indesign' document before running this script.");

          return;

          }

          var docRef = app.documents[0];

          $.sleep( 3000 ); // Just my novice delay method

          updateGraph();

          $.sleep( 3000 ); // Ditto here

          //updateGraph();// done this twice because there seems to be a bug where the dataset is not getting updated first time around

          $.sleep( 3000 );
          //} //end for
          updateLinks(docRef);

          };

          // Reverse loop to do this

          function updateLinks(docRef) {

          for (var i = docRef.links.length-1; i >= 0; i--) {

          //if (docRef.links[i].status == LinkStatus.linkOutOfDate) {

          docRef.links[i].update();
          // } if clause end
          }// for

          }

          // A basic Bridge Talk example

          function updateGraph() {

          if ( BridgeTalk.isRunning( "bridge" ) ) {

          var bt = new BridgeTalk();

          bt.target = "illustrator";

          bt.body = "#target illustrator" + "\r"
          + "var DBHelper = {" + "\r"

          + "mainFs: null," + "\r"

          + "myDoc: null," + "\r"
          + "loadFile: function(fileOrFilename, isAI) {" + "\r"
          + "var _fl = (fileOrFilename instanceof 'File') ? fileOrFilename : new File(fileOrFilename);" + "\r"
          + " if(isAI) { this.myDoc = app.open(_fl);}" + "\r"
          + "else {" + "\r"
          + "this.myDoc.importVariables(_fl);" + "\r"
          + "this.mainFs = app.activeDocument.path.fullName + '/' + app.activeDocument.name;" + "\r"
          + "this.myDoc.save();" + "\r"
          + "this.myDoc.close(SaveOptions.SAVECHANGES);" + "\r"
          + "$.sleep( 3000 );" + "\r"
          + "this.loadFile(this.mainFs,true);" + "\r"
          + "}" + "\r"
          + "}," + "\r"
          + "displaySet: function(setName) {" + "\r"
          + "this.myDoc.activeDataset = this.myDoc.dataSets.getByName(setName);" + "\r"
          + "this.myDoc.activeDataset.display();" + "\r"
          + "this.myDoc.close(SaveOptions.SAVECHANGES);" + "\r"
          + "$.sleep( 3000 );" + "\r"
          + "}" + "\r"
          + "}" + "\r"

          + "DBHelper.loadFile('/u/adobe indesign/Capella Gross Sector Exposure.ai', true);" + "\r"
          + "DBHelper.loadFile('/u/adobe indesign/Capella Gross Sector Exposure2.xml',false);" + "\r"
          + "DBHelper.displaySet('Capella');" + "\r"
          // Save to modify the link status
          //+ "DBHelper.myDoc.close(SaveOptions.SAVECHANGES);";
          bt.send();

          }
          else
          {
          alert ("Please start Adobe Bridge");
          }
          }
          main();

          • 2. Re: Removing $Sleep in code
            Kasyan Servetsky Level 5

            First of all, you don't need to run Bridge application to use Bridge talk. So these lines are unnecessary:

             

             

            if ( BridgeTalk.isRunning( "bridge" ) ) {

            ...

            }

            else

            {

            alert ("Please start Adobe Bridge");

            }

             

             

            When I was writing my Resize images script — http://kasyan.ho.com.ua/resize.html — I stumbled upon a problem: InDesign attempted to update a linked image before Photoshop finished resizing it. At first, I tried to use $.sleep() but it didn't help. Then I added an empty onResult function:

            bt. = function(resObj) {}

            and this solved the problem — script in InDesign continues only after the script in Photoshop finishes its execution.

             

            It would be a good thing if you posted not only your script, but sample documents as well — indd, ai, xml files — so that we could run the script against them.

             

             

            Kasyan

            • 3. Re: Removing $Sleep in code
              pvisell Level 1

              Hi Kasyan,

               

              I removed all the sleep commands and I put your code in, but it still did not allow illustrator to finish processing before it carried on.

               

              I tried both of the below:

              bt.send();
              bt.onResult = function(resObj) {} // empty function - to wait untill PS finishes processing the file

               

              and

              bt.onResult = function(resObj) {} // empty function - to wait untill PS finishes processing the file

              bt.send();

               

              In debug mode the script just carries on and updates the links even before Illustrator has started up.

               

              The above line is the only thing that I changed.  I assume that is what I should have done.

               

              Thanks.

              • 4. Re: Removing $Sleep in code
                Kasyan Servetsky Level 5

                Hi,

                 

                 

                Adding this line and removing the sleep commands will not solve the problem. I just described the approach that worked for me and may work for you (but I don't promise that it will work). However, the whole script should be rewritten in this case. I can give it a try, when time permits, if you post or send me your sample  files.

                My e-mail is askoldich [at] yahoo [dot] com.

                 

                 

                Kasyan

                • 5. Re: Removing $Sleep in code
                  Muppet Mark-QAl63s Level 4

                  The only way you can make a script wait is to use 'sleep'. What you need to do is have bridge talk sat in a while loop waiting for a response from your illustrator script. Have illustrator return a value after it has done. Also I think in this case you would be better served by using toSource() & having illustrator do eval() at the other end of the bt message body (both these methods are over my head at the minute but heres a sample by someone else that may help you with some of the syntax with waiting and timing out)

                   

                  function GetFilesFromBridge() {

                    var fileList;

                    if ( BridgeTalk.isRunning( "bridge" ) ) {

                       var bt = new BridgeTalk();

                       bt.target = "bridge";

                       bt.body = "var theFiles = photoshop.getBridgeFileListForAutomateCommand();theFiles.toSource();";

                       bt.onResult = function( inBT ) { fileList = eval( inBT.body ); }

                       bt.onError = function( inBT ) { fileList = new Array(); }

                       bt.send();

                       bt.pump();

                       $.sleep( 100 );

                       var timeOutAt = ( new Date() ).getTime() + 5000;

                       var currentTime = ( new Date() ).getTime();

                       while ( ( currentTime < timeOutAt ) && ( undefined == fileList ) ) {

                          bt.pump();

                          $.sleep( 100 );

                          currentTime = ( new Date() ).getTime();

                       }

                    }

                    if ( undefined == fileList ) {

                       fileList = new Array();

                    }

                    return fileList;

                  }

                   

                  the target that you want to test 'is running' here is 'illustrator' no point in sending a message if its not

                   

                    if ( BridgeTalk.isRunning( "illustrator" ) ) {

                  }

                  • 6. Re: Removing $Sleep in code
                    Bob Stucky Adobe Employee

                    $.sleep() will absolutely not do what you want. $.sleep() is not a "sleep". It's essentially a tight no-op loop that burns processor power. Except for exceedingly rare situations one never needs it.

                     

                    When using the send() method of a BridgeTalk message, if you do not provide a timeout value, the call is asyncrhonous. If you provide a timeout value, the send method does not return until the target has processed the message or the "timeout" number of seconds has elapsed.

                     

                    So use something like: bt.send( 30 )

                     

                    The send method will wait for a maximum of 30 seconds for the AI call to complete.

                     

                    Also, writing remote functions that way is hard. Try something more like this:

                     

                     

                    function myRemoteFunction() {

                    alert( "howdy" );

                    }

                     

                    var bt = new BridgeTalk();

                    bt.target = "illustrator";

                    bt.body = myRemoteFunction.toSource() + "\n" + "myRemoteFunction();"

                    bt.send( 30 );

                     

                     

                    No matter what - stop using that $.sleep() nonsense.

                     

                     

                    Regards

                     

                    Bob

                    2 people found this helpful
                    • 7. Re: Removing $Sleep in code
                      Muppet Mark-QAl63s Level 4

                      Bob, Im pretty new to this JS stuff so sorry if I gave some duff advice (was only trying to help whilst making head n tail of this myself)

                      I went back to my guide to check and Im stuck with learning using CS2 there is no time parameter of send()?

                      I did find it in CS3 guides so Im guessing it was introduced then? I can't use your method until my bosses get their hands in their pockets n gets me some better software to work with. Is there anything I can do to improve until then? Thanks…

                      • 8. Re: Removing $Sleep in code
                        Bob Stucky Adobe Employee

                        Sorry, didn't realize it was CS2. But still avoid $.sleep(). Your machine slowed down because sleep was hogging the processor.

                         

                        There are 2 ways I used to handle that. First, chain the scripts via bridgetalk. The function in AI includes a BT call back to ID that will execute the rest of the ID script.

                         

                        function aiRemote(){

                          // do magical AI stuff here...

                          function idReturnCall() {

                              // do the stuff in ID that you need to do when AI is done

                          }

                          var bt = new BridgeTalk();

                          bt.target = "indesign";

                          bt.body = idReturnCall.toSource() + "\n" + "idReturnCall();";

                          bt.send();

                        }

                         

                        // do ID initial stuff here

                        var bt = new BridgeTalk();

                        bt.target = "illustrator";

                        bt.body = aiRemote.toSource() + "\n" + "aiRemote();";

                        bt.send();

                         

                        The second way is to use bridge to be the hub for all remote scripts. In CS2, Bridge's scripting engine is persistent. You can set the scripts to load on startup, showing a menu in the Tools menu to execute the script. You can also have a stub script in ID that calls bridge to execute the script. Then the script in Bridge executes the first part of the ID script, then the AI script, then the remainder of the ID work.

                         

                        Both are complex. But with CS2, that's the best you have.

                         

                        Regards

                         

                        Bob

                        • 9. Re: Removing $Sleep in code
                          Muppet Mark-QAl63s Level 4

                          Bob its me thats stuck with CS2 (for now) the OP may well be able to take advantage of your solution so that is good. I will just have to wait probably much of what Im try to learn at the moment will have changed n I'll be back near square 1 when I do get to up grade. I will have a play with that method. So thanks. I've moving over from the Applescript side where inter application communication as easy as 'set x to somevalue tell whatever to use it… Im finding bridgeTalk much tougher…

                          • 10. Re: Removing $Sleep in code
                            Kasyan Servetsky Level 5

                             

                            Hi pvisell,

                             

                            I think you overcomplicated things in the script you posted.

                             

                             

                            Here is my implementation of what I suggested in post #2.

                             

                            The key points are:

                            1. Define an empty onResult function

                            bt.onResult = function(resObj) {}

                             

                             

                            2. provide a timeout value for send method as Bob advised (and I forgot to mention in my previous post)

                            bt.send(30);

                             

                             

                            I don't know why we should do both of these things — I found this out by experimenting.

                             

                            Interapplication communication with scripts is explained very obscurely in documentation, so it's hard to understand. But once you sorted it out — it's easy. I would never understood this on my own, if Bob hadn't helped me. Thanks Bob a lot for this!!!

                             

                             

                            Kasyan

                             

                            //-----------------------------------------

                            #target indesign

                             

                            var myXmlPath = "/c/Test/Capella Gross Sector Exposure.xml";
                            var mySetName = "Capella";

                             

                            var myDoc = app.activeDocument;
                            ProcessLinks();
                            UpdateLinks()
                            alert("Done");

                             

                            // ------------------------- FUNCTIONS -------------------------
                            function ProcessLinks() {
                                for (var j = 0; j < myDoc.links.length; j++) {
                                    var myLink = myDoc.links[j];
                                    CreateBridgeTalkMessage(myLink.filePath, myXmlPath, mySetName);
                                }
                            }

                            function CreateBridgeTalkMessage(myAiPath, myXmlPath, mySetName) {
                                var bt = new BridgeTalk();
                                bt.target = "illustrator";
                                var myScript = UpdateDataset.toString() + '\r';
                                myScript += 'UpdateDataset(\"' + myAiPath + '\", \"' + myXmlPath + '\", \"' + mySetName + '\");';
                                bt.body = myScript;
                                bt.onResult = function(resObj) {}
                                bt.send(30);
                            }

                            function UpdateDataset(myAiPath, myXmlPath, mySetName) {
                                var myAiFile = new File(myAiPath);
                                var myDoc = app.open(myAiFile);
                                var myXmlFile = new File(myXmlPath);
                                if (myXmlFile.exists) {
                                    myDoc.importVariables(myXmlFile);
                                    myDoc.activeDataset = myDoc.dataSets.getByName(mySetName);
                                    myDoc.activeDataset.display();
                                    myDoc.close(SaveOptions.SAVECHANGES);
                                }
                            }

                            function UpdateLinks() {
                                for (var i = myDoc.links.length-1; i >= 0; i--) {
                                    if (myDoc.links[i].status == LinkStatus.linkOutOfDate) {
                                        myDoc.links[i].update();
                                    }
                                }
                            }

                            • 11. Re: Removing $Sleep in code
                              pvisell Level 1

                              Hi,


                              Thank you everyone for your help.  Especially Kasyan and Bob.  The code works perfectly and is much neater too!