【问题标题】:Is there an equivalent of setTimeout in Adobe's ExtendScriptAdobe的ExtendScript中是否有等效的setTimeout
【发布时间】:2012-05-28 21:49:37
【问题描述】:

Javascript 的setTimeout 函数是window 对象的一个​​方法。此对象在 ExtendScript 中不存在,因此不可用于为 Adob​​e InDesign 或 Illustrator 制作的脚本。我可以改用什么来获得相同的结果?

【问题讨论】:

    标签: adobe settimeout extendscript adobe-indesign


    【解决方案1】:

    它是扩展脚本的$ 对象的一部分。

    $.sleep(1000) //tell extendscript to sleep 1000 milliseconds
    

    与 setTimeout() 不同,但你应该能够让它为你工作。

    编辑:这是扩展脚本的 setTimeout 扩展:

    $.setTimeout = function(func, time) {
            $.sleep(time);
            func();
    };
    
    $.setTimeout(function () {alert("hello world")}, 3000);
    

    【讨论】:

    • +1,但实际上,我的上下文需要能够取消超时。基本上,我正在启动一个外部应用程序并汇集某个日志文件以检测该应用程序的终止。启动 10 秒后,我宣布操作“超时”,假设外部应用程序出现故障。所以我需要像var t = setTimeout(stopPooling, 10000) 这样的东西。如果通过池化日志我可以确定外部应用程序成功终止(不到10秒),那么我需要取消超时(clearTimeout(t)),以免不必要地调用stopPooling
    • 如果你可以测试运行外部应用程序是否成功,你不能将func();修改为if(!appRan) func();吗?我不知道如何在扩展脚本中编写 clearTimeout()。
    • 我想是的。但我有两件不同的事情要做。我想每 0.1 秒汇集一次我的日志文件,并在 10 秒后超时。像var t, i; i=setInterval(function() { if(appRan) { clearInterval(i); clearTimeout(t); handleAppSuccess(); }}, 100); t=setTimeout(function() { clearInterval(i); handleAppFailed(); }, 10000); 这样的东西我想我可以用$.sleep 使用计数器来做到这一点:for(c=0; c<100; ++c){ $.sleep(100); if(appRan){ success=true; c=101; }} if(success){ handleAppSuccess(); } else { handleAppFailed(); },但其他情况可能需要真正的非阻塞方法......
    • 这也不会在事件循环结束时展开堆栈/推送任务。
    • 这对于等待像 app.executeCommand 这样的异步操作完成很有用
    【解决方案2】:

    有一个 setTimeout ExtendScript 实现 here(德国网站,代码用英文注释),但由于它依赖于 app.idleTasks,它只能在 InDesign 中工作(没有 Photoshop)。

    我将上面链接中的可下载代码粘贴到此处 (© Andreas Imhof):

    /**
     * setTimeout
     * Version 1.0
     * A setTimeout function implementation for InDesign ExtendScript like known from a Browser's Javascript.
     * Uses InDesign's idleTask stuff.
     * Timeout milliseconds are not accurate, but it allows to call a heavy load script,
     * split it up into small junks for InDesign is not blocked too long and has time to breath.
     *
     * The script MUST run in its dedicated target engine:
     * #target "InDesign"
     * #targetengine "myOwnEngineName"
     *
     * DISCLAIMER:
     * No warranty - use as is or modify but retain the originator's coordinates:
     * CopyRight Andreas Imhof, www.aiedv.ch, ai@aiedv.ch
     */
    //
    var setTimeout_Task_curfile = new File($.fileName),
    setTimeout_Task_curfullname = decodeURI(setTimeout_Task_curfile.name),
                    // setTimeout_Taskname must be a UNIQUE name, so we take it from the current running script!! 
                    // May be set to any String like
                    // setTimeout_Taskname = 'myOwnTask';
    setTimeout_Taskname = setTimeout_Task_curfullname.lastIndexOf(".") > 0 ? (setTimeout_Task_curfullname.substr(0,setTimeout_Task_curfullname.lastIndexOf("."))) : setTimeout_Task_curfullname,
    
    setTimeout_Tasks = {},  // all defined tasks prepared to run
    /**
     * setTimeout_hasIdleTask
     * Utility function
     * @param {Number} the timeout task id
     * @return {Boolean} true if a given timeout id also has his attached idleTask
     */
    setTimeout_hasIdleTask = function(id) {
      var has = false, i;
      for (i = 0; i < app.idleTasks.length; i++) {
        //alert("id: " + id + " tid: " + app.idleTasks[i].label);
        if (app.idleTasks[i].isValid && (app.idleTasks[i].id === id)) {
          has = true;
          break;
        }
      }
      return has;
    },
    /**
     * setTimeoutList
     * Utility function
     * @return {String} a list of all currently active setTimeout_Tasks
     */
    setTimeoutList = function() {
      var list = "", cb,
        k;
      for (k in setTimeout_Tasks) {
        if (list !== "") list += ",";
        cb = setTimeout_Tasks[k]["cb"].toString();
        cb = cb.replace(/\s/g,"");
        list += setTimeout_Tasks[k]["taskid"] + ":" + cb;
      }
      return list;
    },
    /**
     * idleTasksList
     * Utility function
     * @return {String} a list of all currently active idleTasks
     */
    idleTasksList = function() {
      var list = "",
        k;
      for (k = 0; k < app.idleTasks.length; k++) {
        if (list !== "") list += ",";
        list += app.idleTasks[k].id + ":" + setTimeout_hasIdleTask(app.idleTasks[k].id) + ":" + app.idleTasks[k].label;
      }
      return list;
    },
    /**
     * setTimeoutInit
     * Init/clean the timeout system
     */
    setTimeoutInit = function() {
      var it;
      // remove all (erroneous) idleTasks
      //alert("set idleTasks: " + app.idleTasks.length);
      //NA: logmess("setTimeoutInit set idleTasks: " + app.idleTasks.length + "\n");
      for (it = 0; it < app.idleTasks.length; it++) {
        if (app.idleTasks[it].label == setTimeout_Taskname) {
          //alert("removing idleTask id " + app.idleTasks[it].id + " label: " + app.idleTasks[it].label);
          clearTimeout(app.idleTasks[it].id);
        }
      }
      setTimeout_Tasks = {};
    },
    /**
     * Tasks Handler
     * Check if a task can be called now
     * @param {Number} taskid
     * @return {Boolean} always false
     */
    setTimeoutHandler = function(taskid) {
      var now_Ticks = new Date().getTime(),
        cb, cb_retval = undefined;
    
      try {
        //alert("taskid: " + taskid + "\nnumcalls: " + setTimeout_Tasks[taskid]["numcalls"]);
        // we look for well timed call only!!!  CS6 calls at start AND after the timeout
        if (setTimeout_Tasks[taskid]["end_ticks"] > now_Ticks) {    // we have not reached timeout
          //NA: logmess("setTimeoutHandler id " +  taskid + " too early by ms: " + (setTimeout_Tasks[taskid]["end_ticks"] - now_Ticks) + "\n");
          //alert("setTimeoutHandler id " +  taskid + " too early by ms: " + (setTimeout_Tasks[taskid]["end_ticks"] - now_Ticks));
          setTimeout_Tasks[taskid]["numcalls"] += 1;
          return false; // wait for next call
        }
      }
      catch(ex) {
        alert("Exception (1) in function 'setTimeoutHandler()', taskid " + taskid + ":\n" + ex);
      }
    
      try {
        cb = setTimeout_Tasks[taskid]["cb"];    // store the callback
        clearTimeout(taskid);   // remove the timeout
      }
      catch(ex) {
        alert("Exception (2) in function 'setTimeoutHandler()', taskid " + taskid + ":\n" + ex);
      }
    
      try {
        //NA: logmess("setTimeoutHandler call " +  cb + "\n");
        cb_retval = cb();   // call the cb
        //if (cb_retval) alert("cb_retval:\n" + cb_retval);
      } catch(ex) {
        alert("Exception in function '" + cb() + ":\n" + ex);
      }
    
      return false;
    },
    /**
     * setTimeout
     * Set a function to called after the given timeout
     * @param {function} callback the function to call
     * @param {Number} timeout in ms
     * @return {Boolean} null on error, otherwise the id (can be used with clearTimeout
     */
    setTimeout = function(callback,timeout) {
      try {
        var idle_Task,
          now_Ticks = new Date().getTime();
        idle_Task = app.idleTasks.add({sleep:timeout});
        idle_Task.label = setTimeout_Taskname;
        setTimeout_Tasks[idle_Task.id] = {
          "label": setTimeout_Taskname,
          "start_ticks": now_Ticks,
          "sleep": timeout,
          "end_ticks": now_Ticks + timeout,
          "cb": callback,
          "taskid": idle_Task.id,
          "numcalls": 0
          };
        setTimeout_Tasks[idle_Task.id].handler = function(ev){setTimeoutHandler(setTimeout_Tasks[idle_Task.id]["taskid"]);};
        idle_Task.addEventListener(IdleEvent.ON_IDLE, setTimeout_Tasks[idle_Task.id].handler,false);
        //NA: logmess("setTimeout idle_Task.id: " + idle_Task.id + ", timeout: " + timeout + "\ncallback: " + callback + "\n");
        return idle_Task.id;
      }
      catch(ex) {
        alert("Exception in function 'setTimeout()':\n" + ex);
      }
      return null;
    },
    /**
     * clearTimeout
     * Clear the timeout given by the setTimeout return value
     * @param {Number} id the timeout id to clear
     */
    clearTimeout = function (id){
      var i, task = null;
      for (i = 0; i < app.idleTasks.length; i++) {
        //alert("id: " + id + " tid: " + app.idleTasks[i].label);
        if ((app.idleTasks[i].id == id) && app.idleTasks[i].isValid) {
          task = app.idleTasks[i];
          break;
        }
      }
    
      if (task !== null) {
        try {
          if (setTimeout_Tasks[id] && setTimeout_Tasks[id].handler) {
            // this kills any!!!    app.idleTasks.itemByID(id).removeEventListener(IdleEvent.ON_IDLE, setTimeout_Tasks[id].handler,false);
            task.removeEventListener(IdleEvent.ON_IDLE, setTimeout_Tasks[id].handler,false);
          }
          // this kills any!!!    app.idleTasks.itemByID(id).remove();
          //task.remove();
          task.sleep = 0;
        }
        catch(ex) {
          alert("Exception in function 'clearTimeout() idleTasks':\n" + ex);
        }
        try {
          delete setTimeout_Tasks[id];
        }
        catch(ex) {
          alert("Exception in function 'clearTimeout() delete setTimeout_Tasks':\n" + ex);
        }
      }
    };
    /**
     * Init/clean the timeout system
     */
    setTimeoutInit();
    // alert(setTimeout_Taskname);  // Just to check if the 'setTimeout_Taskname' was set correctly
    

    【讨论】:

      【解决方案3】:

      在 Adob​​e After Effects 中使用 $.sleep(time) 会导致脚本停止。

      改为在 ExtendScript 中使用原生 app.scheduleTask(stringToExecute, delay, repeat)

      例子:

      var taskId = app.scheduleTask(function () {alert("hello world")}, 1500, false);
      

      取消:

      app.cancelTask(taskId);
      

      【讨论】:

      • 如何避免Error: ReferenceError: app is not defined
      • @TheKill-996 app 是外部 .jsx 脚本文件的 Extendscript 的一部分(例如,当您在图层属性上使用表达式时除外)。请参阅ae-scripting.docsforadobe.dev/general/application/… - 我认为我实际上犯了一个错误,app.setTimeout() 本身不支持,我认为 After Effects 中的标准教程面板之一添加了该例程。
      • 在 Photoshop 中 app.scheduleTask is not a function。知道如何解决这个问题吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-22
      • 2018-05-03
      • 2020-09-22
      • 1970-01-01
      • 2012-05-24
      相关资源
      最近更新 更多