• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Removing $Sleep in code

New Here ,
Nov 23, 2009 Nov 23, 2009

Copy link to clipboard

Copied

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.

TOPICS
Scripting

Views

2.1K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Guru , Nov 29, 2009 Nov 29, 2009

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 do

...

Votes

Translate

Translate
New Here ,
Nov 23, 2009 Nov 23, 2009

Copy link to clipboard

Copied

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.status == LinkStatus.linkOutOfDate) {

docRef.links.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();

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Nov 27, 2009 Nov 27, 2009

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Nov 27, 2009 Nov 27, 2009

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Nov 27, 2009 Nov 27, 2009

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Nov 27, 2009 Nov 27, 2009

Copy link to clipboard

Copied

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" ) ) {

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Nov 27, 2009 Nov 27, 2009

Copy link to clipboard

Copied

$.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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Nov 27, 2009 Nov 27, 2009

Copy link to clipboard

Copied

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…

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Nov 27, 2009 Nov 27, 2009

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Nov 27, 2009 Nov 27, 2009

Copy link to clipboard

Copied

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…

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Nov 29, 2009 Nov 29, 2009

Copy link to clipboard

Copied

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;
        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.status == LinkStatus.linkOutOfDate) {
            myDoc.links.update();
        }
    }
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Nov 30, 2009 Nov 30, 2009

Copy link to clipboard

Copied

LATEST

Hi,


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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines