2017-08-25 125 views
0

我在Adobe的Flex 4(ActionScript 3的)的函数,它接受一个对象,并返回一个ArrayCollection ...在ActionScript创建延迟3个功能

如果某个全局变量设置为true,我想要的功能在运行之前延迟3秒。否则,我希望该功能正常运行。

的问题是,如果我用一个定时器,该定时器调用单独功能,以及任何函数不能返回我的调用函数,也不能调用函数接受任何参数,所以它不喜欢我可以在TimerComplete事件触发后递归地调用我自己的函数...并且递归调用将不起作用,因为它会将ArrayCollection返回到定时器结果函数,而不是返回原始调用函数...

I需要延迟以内的这个函数,而不是延迟,导致我超出这个函数。但我无法弄清楚如何去做。

像这样的东西是什么,我需要做的:

private function createArrayCollection(myObject:Object):ArrayCollection { 

    var myArrayCollection:ArrayCollection = new ArrayCollection(); 

    if (globalWaitBoolean) { 
     //delay here for 3 seconds, somehow 
    } 

    //Here I do the stuff that uses the info in myObject to figure out what to 
    //put into the ArrayCollection I want to return 

    return (myArrayCollection); 
} 

所以......关于如何做到这一点,而无需调用外部定时器功能无法返回一个对象回到我原来的功能,任何想法?

感谢,

回答

2

你想要的方式,你将有你的整个应用程序滞后3秒,反应迟钝到任何用户输入和外部事件。但它是可能的,肯定的:

import flash.utils.getTimer; 

private function createArrayCollection(myObject:Object):ArrayCollection 
{ 
    var myArrayCollection:ArrayCollection = new ArrayCollection; 

    if (globalWaitBoolean) 
    { 
     var waitUntil:int = getTimer() + 3000; 

     // Method getTimer() returns time in ms passed since app start. 
     // So you just have to wait until it is greater than appointed time. 
     while (getTimer() < waitUntil) 
     { 
      // Do nothing. 
     } 
    } 

    return (myArrayCollection); 
} 

不过,如果你想这样做,在做这件事的正确方式:

import flash.utils.setTimeout; 

private function callerMethod():void 
{ 
    // Blah blah blah. 
    // ... 
    // Finally. 
    createArrayCollection(sourceData, asyncResult); 
} 

private function createArrayCollection(myObject:Object, handler:Function):void 
{ 
    var result:ArrayCollection = new ArrayCollection; 

    if (globalWaitBoolean) setTimeout(handler, 3000, result); 
    else handler(result); 
} 

private function asyncResult(source:ArrayCollection):void 
{ 
    // The rest of your processing code. 
} 
+0

是的,不幸的是,无法完成正确的方式,因为调用者程序是一个Adobe AIR程序,如果不在数百台客户机上更新它,我无法更改它 - 程序调用的函数在“模块“只有一个客户端遇到问题,因此为一个客户端修改模块要比为数百个客户端修改AIR应用程序要容易得多。因此,我需要这种荒谬的,不正确的编程实践,使它只为这个客户工作。非常感谢您的答复 - 这正是我所期待的。 –

+0

哦 - 仅供参考,如果我在while循环中添加一行说this.ValidateNow(),我认为它可能实际上允许与程序交互,而它正在等待定时器通过。至少,我会尝试一下,看看会发生什么。即使它将程序锁定3秒钟,也只有一个客户端会遇到这个问题,而且每隔一段时间就会遇到一次。 –

+0

@LaurenceMacNeill不,它不会。 Flash应用程序对AS3脚本有一个执行线程,所以在遍历这个空循环时它不会做任何事情。 – Organis

1

普通(同步)码流不会返回,直到值已准备好,所以如果您希望实际等待3秒钟,而不允许应用程序执行任何操作,请使用@ Organis的答案的getTimer()方法。如果你想要获得异步结果,你需要面对并克服更多的问题。

首先,您预计何时会返回ArrayCollection实际到达。谈到代码设计,异步代码需要大量的假设,线程安全等等,即使AS3/Flash没有真正的多线程,除非您计数为Worker s,但带有事件的代码流并不那么明显。所以,不管谁打电话给你的人,都不应该期望从它返回的价值马上。所以,谈到你的直接问题,不,如果你需要一个响应式应用程序,你不能避免某种定时器。但是你可以通过一种涉及间接返回结果的方法来使用它们。

其次,如果您的应用程序需要这些对象,是否可能会有来自对象的更多数组集合的同时请求 - 您必须为可能由此造成的任何干扰做准备。假设你的功能是通过点击按钮触发的 - 如果该按钮在3秒内被点击多次,该怎么办?

第三,处理代码的实际路由不是直接与异步返回。您需要一个回调函数,一个事件处理函数(本质上是一个半原生的回调函数),一个定期检查值存在的代码(输入帧处理函数等)或类似的技巧来收集异步返回的值,然后传递它涉及任何相关的代码,将进一步处理它。因此,您需要设计一个能够接收复杂数据的接口(源对象向前,数组收集向后),然后针对所有可能的情况和缺陷仔细测试它。

一个实现所有这些很长的例子,我会尽力以某种方式概述它。 Ler假设你有一种“服务器”类,它接受数据请求并同步处理(不等待)或异步处理(等待)。它接受类型为“T”的源对象,并提供一个类型为ArrayCollection的新创建对象,该对象作为参数提供给发送给它的任何回调函数。它也接受延迟(一种简单的方式来显示同步/异步返回将是一个布尔值,但为什么不获得一个int?)作为参数,并保证(在事件模型限制的范围内),在这个延迟之后,回调将被称为尽快。架构将如下所示:

class Processor { 
    Dictionary requests; // here all the requests that are delayed will be stored 
    public function dpr(source:T,callback:Function,delay:int=0):void{...} 
    // creates requests and stores them 
    private function syncProcess(source:T):ArrayCollection {...} 
    // whatever routine you want to get variably delayed 
    private function processTimeout(e:Event=null):void {...} 
    // processes events from "setTimeout()" and calls callbacks 
} 

请注意,异步方法被迫创建三个实体,而不是同步实例。首先是请求保持结构(字典在这里),第二是超时事件处理程序,第三是你希望在数据准备好时调用的回调。码流会是这样的:

同步调用,会导致从类中直接调用回调:request - >processTimeout - >syncProcess() - >callback。异步呼叫将在Timer::timerComplete事件处理程序中通过调用request中的setTimeout调用回调,最初来自request的数据存储在requests中。

+0

这是一个调用该函数的Adobe AIR应用程序,该应用程序包含在AIR应用程序加载的Flex“模块”中。 AIR应用程序*应该等待,直到它在执行其他任何操作之前获取ArrayCollection。该模块创建打印作业,其中一个打印作业*可能是信封,比普通打印作业花费的时间更长。如果我不停止这个过程并等待信封打印,Windows会很乐意将这份打印作业存储很长时间,并在多个作业结束后将其打印出来 - 从而使所有内容都不可用-订购。我不知道为什么。 –

+0

而且,是的,停止一切等待一个愚蠢的信封打印是一个彻头彻尾的黑客工作。但在这一点上,我已经耗尽了所有我能想到的东西。这是一个Windows问题,不幸的是,我的Flex“模块”内部几乎没有任何Windows控制。 –

+0

Hm-m-m。使用AS3打印是我从未真正做过的事情,是的,可能存在问题。不过,我想知道,如果您真的可以在AS3应用程序中拆分作业,以便正常工作首先进行,那么如果存在该信封,则会延迟该信封,并显示一个弹出窗口,如“准备就绪时单击”,然后将该信封发送给打印机? – Vesper

1

你可以使用嵌入式/内联函数:

private function createArrayCollection(myObject:Object):ArrayCollection { 

    var myArrayCollection:ArrayCollection = new ArrayCollection(); 

    if (globalWaitBoolean) { 
     var milliseconds:int = 3000; 
     //delay here for 3 seconds 
     setTimeout(function() 
     { 
      //Here I do the stuff that uses the info in myObject to figure out what to 
      //put into the ArrayCollection I want to return 
      return (myArrayCollection); 
     }, 
     milliseconds); 
    } 
    else 
    { 
     //Here I do the stuff that uses the info in myObject to figure out what to 
     //put into the ArrayCollection I want to return 
     return (myArrayCollection); 
    } 
} 

的内部函数可以访问外部函数的所有本地变量。