主题:  Timeout Objects

jerrowolf

职务:普通成员
等级:1
金币:0.0
发贴:83
注册:2001/1/4 20:28:12
#12001/5/21 8:34:03
Timeout Objects

by David Berger

It is often the case that you need to trigger events after a certain amount of time or at regular intervals. For example: you are streaming in a Shockwave movie and you want to check the mediaReady property of a certain member every 2 seconds to find out when it's ready for use. Once it is ready you do not need to check it again.

Traditionally this sort of programming involved variations of keeping track of elapsed time in global variables or object and behavior properties. Sometimes the timer was used. Often the scripts involved manipulating the actorList and relying on stepFrame messages. These techniques frequently lead to buggy and difficult-to-read code. With the introduction of timeout objects in Director 8 there is now a more elegant solution.

The basic idea is that you create a timeout object. You tell the timeout object what handler you want executed at given time intervals. The timeout object gets added to the timeoutList which is a system property containing a linear list of active timeout objects. Each timeout object in the timeoutList gets processed automatically until you explicitly remove it with the forget function. The new function is used to create timeout objects.

timeout ("thetimeOutName").new (1000, #theHandlerToCall, theTarget)

Each timeout object is identified by a string value used for the name. The name of the timeout object in the example above is "thetimeOutName".

The second parameter of the new function specifies which handler should get called when the timeout is triggered. This is stored in the timeoutHandler property of the object. Notice that you pass in the handler name as a symbol.

The first parameter specifies how often the timeoutHandler should get called. It is measured in milliseconds, so in the example, theHandlerToCall gets called every second. This is stored in the period property of the timeout object.

The third parameter specifies the location of the timeoutHandler. This is stored in the target property of the timeout object. If the target is blank, Director will look for the handler in a movie script. I prefer to set up timeout handlers and keep the handlers I want called within an instance of a parent script. In that case you pass me as the target.

Try executing the code in the message window.

timeout ("thetimeOutName").new (1000, #theHandlerToCall, theTarget)
put the timeoutlist
-- [timeOut("thetimeOutName")]


Here is the code for the movie with comments.

on prepareMovie
--create the timeoutobject
timeout ("annoyTheUser").new (5000, #callAlert)
end


on callAlert
alert "Click the button."
end

on buttonClicked
--remove the timeoutoject from the timeoutlist when the button is clicked
timeout ("annoyTheUser").forget ()
end

timeout objects are especially useful for asynchronous operations such as many of the Net Lingo Calls. A typical call looks like:

gnetid = getnettext ("http://www.mysite.com/mytext.htm")

The timeout object can periodically check to determine if the operation is done. While this was often done in an exitFrame handler, you can now check with a timeout object. Add the timeout object after the call to getNetText and add a handler in a movie script to check for the operation when called .

timeout ("checkNetOperation").new (1000, #checktheNetOperation)

on checktheNetOperation
if netdone (gnetid) then
--if the operation is done kill the timeout object
timeout ("checkNetOperation").forget ()
if neterror (gnetid) = "OK" then
res=netTextResult (gnetid)
--do the rest of the processing
process res
end if
end if
end

I also use timeout objects when I want two Shockwave movies to pass information to each other. The first movie adds a timeout object that calls a handler which polls for the existence of a preference file of a given name by calling the getPref function every few seconds. When the second movie needs to pass data, it writes to the preference file. As soon as the first movie gets data from the file, it can kill the timeout object using the forget function. Basically, timeout objects are so useful that if you are still using Director 7, you might want to upgrade just for this feature.

--中文

定时对象

--著:David Berger
--译:jerrowolf
我们经常要作这样的事情,每隔一段时间就去触发一个事件。例如,当你组建一个shockwave电影时,可能会要每隔2秒钟去测试一下一个特定成员的mediaReady属性以便于判断何时它可以使用。一旦它准备好了,就不需要再判断了。

编写这样的程序,一般会用全局变量或者对象和行为属性来跟踪时间变化。有时用到the timer。这样的脚本经常会对演员表进行操作,并且通过帧的步进来传递消息。这样的方法经常会产生bug,并且很难阅读。在Director8当中,我们可以利用定时对象来探索一个比较明智的解决方案。

基本的方法就是,你先创建一个定时对象。然后告知它在给定的时间间隔内执行什么样的句柄。定时对象会被加入到timeoutlist列表,这个列表是系统属性,是当前激活的定时对象的线形列表。列表中的每一个定时对象都会自动地执行,除非你用forget方法将其移除。创建定时对象使用new方法。

timeout ("thetimeOutName").new (1000, #theHandlerToCall, theTarget)

每一个定时对象都用一个字符串作为名字来标识。上例中定时对象的名字是"thetimeOutName".new方法中的第二个参数用来指出,当指定时间间隔之后,需要执行的句柄。这个句柄名被储存在对象的timeoutHandler属性中。注意你必须把句柄名写成符号形式。

第一个参数指出经过多长时间才执行timeoutHandler句柄。也就是时间间隔。格式是毫秒,在上例中,每隔一秒钟执行一次句柄。这个时间存储在对象的period属性当中。

第三个参数指定timeoutHandler句柄的位置。他被存储在定时对象的the target 属性当中,如果the target为空,则Director会在电影脚本中寻找相应的句柄,我更喜欢建立一个父脚本,把我想要调用的句柄放在父脚本中,这样我可以从父脚本的一个实例当中调用句柄,你可以使用me来做为the target。

在消息窗口中试着输入以下代码:

timeout ("thetimeOutName").new (1000, #theHandlerToCall, theTarget)
put the timeoutlist
-- [timeOut("thetimeOutName")]

以下是一个电影中的代码(带注释)

on prepareMovie
--创建定时对象
timeout ("annoyTheUser").new (5000, #callAlert)
end


on callAlert
alert "Click the button."
end

on buttonClicked
--点击按钮时,从timeoutlist中清除掉这个定时对象。
timeout ("annoyTheUser").forget ()
end


定时对象在进行异步操作时尤其有用,例如在netlingo中的很多调用,典型的调用这样写:

gnetid = getnettext ("http://www.mysite.com/mytext.htm")

定时对象可以周期性地检查是否操作已经进行,以往我们需要不听地在exitframe句柄中判断,现在你可以用一个定时对象来检查,在调用getNetText后面加上一个定时对象,然后在电影脚本中加入一个句柄,调用这个句柄时就检查是否进行了某种操作。

代码如下:

timeout ("checkNetOperation").new (1000, #checktheNetOperation)

on checktheNetOperation
if netdone (gnetid) then
--if the operation is done kill the timeout object
timeout ("checkNetOperation").forget ()
if neterror (gnetid) = "OK" then
res=netTextResult (gnetid)
--do the rest of the processing
process res
end if
end if
end

我还经常使用定时对象来在两个shockwave电影之间传递信息。第一个电影中添加了一个定时对象,它每隔几秒钟调用一个句柄,这个句柄用来检查由getPref方法指定名字的文件是否存在,当第二个电影需要传递数据时,它将数据写入指定文件中,当第一个电影从文件中取得数据时,马上通过forget方法去掉定时对象。总之,定时对象非常有用,如果你还在使用Director7,那么,赶紧升级来体验一下这些新东西吧。

编辑历史:[这消息被flyingbird编辑过(编辑时间2001-05-21 12:30:19)]


Call Me Simon

职务:普通成员
等级:2
金币:2.0
发贴:646
注册:2000/9/19 13:56:51
#22001/5/21 12:31:23
Well done!

Thanks for sharing!