Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
api:event:zh [2023/09/24 08:24]
hfsr [Event API] translate to zh_cn
api:event:zh [2023/11/29 13:11] (current)
hfsr [通用事件处理函数]
Line 1: Line 1:
-====== Event API ====== +====== Event(事件) ​API ====== 
- +Event(事件) API为用户提供了一套基本的事件处理系统,可利用其编写代码以响应操作系统或其他程序/​运行库传递的[[component:​signals|信号]]。
-**本篇文章的部分/​全部内容还没有进行翻译。** +
- +
-Event(事件)API提供了一套基本的事件处理系统,用户可利用其编写代码以响应操作系统或其他程序/​运行库传递的[[component:​signals|signals]]。+
  
 例如,你可以利用此API捕获按下的按键、在外接显示器连接到电脑或断开连接时进行响应,或是处理传入的网络信息。 例如,你可以利用此API捕获按下的按键、在外接显示器连接到电脑或断开连接时进行响应,或是处理传入的网络信息。
  
-===== Overview ​===== +===== 概述 ​===== 
-There are two main use cases for the event API: +event API主要有两种用法:
- +
-- Have your program react on events while running in the background (driver mode). +
-- Have your program handle events while being the foreground program executed (primary mode).+
  
-In driver mode your program needs to register callbacks for events ​(using `event.listen()`) then it should exit to return execution to the primary program (usually the shell). In primary mode your program does not need to register events, it can handle them directly using `event.pull()`.+- 让程序在后台运行时对事件作出响应(驱动模式)。 
 +- 让程序在作为前台程序执行时处理事件(优先模式)
  
-//Note:// While it is technically possible to do both at the same time it is not recommended to do soTo make sure that events ​are received by all registered functions, they are consumed only after all functions have been calledSo if you register your handler and pull at the same time, you would receive events twice.+在驱动模式下,你的程序需要先为事件注册回调函数(用 `event.listen()`函数),然后退出,以继续执行主程序(通常是shell)。 ​  
 +在优先模式下,你无需在程序中注册事件,可以直接使用`events.pull()`函数拉取并处理信号。
  
-===== Functions ​=====+**注意:**虽然从技术层面上讲可以同时使用两种工作模式,但不推荐这样做。为了保证所有已注册的函数都能接收到事件,事件只有在所有函数均被调用后才会被消耗掉。因此如果你注册了处理函数,同时又进行了拉取,那么同一个事件会被响应两次。 
 +===== 函数 ​=====
  
 - `event.listen(event:​ string, callback: function): boolean`  ​ - `event.listen(event:​ string, callback: function): boolean`  ​
-Register a new event listener that should be called for events with the specified name.   +注册一个新的事件侦听器,会在指定名称的事件出现后被调用。 ​  
-**event** - name of the signal to listen to.\\ +**event** - 需要侦听的信号名称。\\ 
-**callback** - the function to call if this signal is received. The function will receive the event name it was registered for as first parameter, then all remaining parameters as defined by the [[component:​signals|signal]] that caused the event.\\ +**callback** - 在收到指定信号后调用的函数。此函数将会接收注册的事件名称作为第一个参数,然后接收触发事件的[[component:​signals|信号]]所定义的所有参数。\\ 
-**Returns:** `number`, the event id which can be canceled via `event.cancel`, if the event was successfully registered, ​`false` ​if this function was already registered for this event type.+**返回值:**若注册成功,数据类型为`number`,代表了事件id,可用于传递给`event.cancel`函数取消事件。若函数已经注册过此类事件,将会返回`false`。   
 +\\
 - `event.ignore(event:​ string, callback: function): boolean`  ​ - `event.ignore(event:​ string, callback: function): boolean`  ​
-Unregister a previously registered event listener. ​  +注销一个先前注册的事件侦听器。 ​  
-**event** - name of the signal to unregister.\\ +**event** - 需要注销的信号名称。\\ 
-**callback** - the function that was used to register for this event.\\ +**callback** - 之前注册到此事件的回调函数。\\ 
-**Returns:** `true` ​if the event was successfully unregistered, ​`false` ​if this function was not registered for this event type.\\ +**返回值:**若事件成功注销则返回`true`。若指定的函数并未注册到此类事件则返回`false`\\ 
-//Note:// An event listeners may return ​`false` ​to unregister themselves, which is equivalent to calling ​`event.ignore` ​and passing the listener with the event name it was registered for.+**注意:**事件侦听器返回`false`后将会注销自身。等价于调用 ​`event.ignore`,并向其传递侦听器函数与所注册的事件名称。 ​  
 +\\
 - `event.timer(interval:​ number, callback: function[, times: number]): number`  ​ - `event.timer(interval:​ number, callback: function[, times: number]): number`  ​
-Starts a new timer that will be called after the time specified in `interval`  +开启一个新的定时器,在经过`interval`指定的时长后将会被触发。 ​  
-**interval** - time in seconds between each invocation of the callback function. Can be a fraction like 0.05.\\ +**interval** - 调用回调函数的间隔时长,单位为秒。可以为像0.05这样的小数。\\ 
-**callback** - the function to call.\\ +**callback** - 要调用的函数。\\ 
-**times** - how many times the function will be called. If omitted the function will be called once. Pass `math.huge` ​for infinite repeat.\\ +**times** - 应调用的次数。若省略则函数只会被调用一次。指定为`math.huge`可以无限次重复调用。\\ 
-**Returns:** a timer ID that can be used to cancel the timer at any time.\\ +**返回值:**定时器id,可以随时用于取消定时器。\\ 
-//Note//: the timer resolution can vary. If the computer is idle and enters sleep mode, it will only be woken in a game tick, so the time the callback is called may be up to 0.05 seconds off.  +**注意:**定时器的精度可能会发生变化。如果电脑闲置并进入了休眠模式,则电脑只会每游戏刻唤醒一次。因此触发回调函数的时间点可能会偏差至多0.05秒。 ​  
 +\\
 - `event.cancel(timerId:​ number): boolean`  ​ - `event.cancel(timerId:​ number): boolean`  ​
-Cancels a timer previously created with `event.timer`  +取消某个先前由`event.timer`函数创建的定时器。 ​  
-**timerId** - a timer ID as returned by `event.timer`.\\ +**timerId** - `event.timer`函数返回的定时器id。\\ 
-**Returns:** `true` ​if the timer was stopped, ​`false` ​if there was no timer with the specified ID.+**返回值:**若定时器被成功终止则返回`true`。若不存在指定id对应的定时器则返回`false`。   
 +\\
 - `event.pull([timeout:​ number], [name: string], ...): string, ...`  ​ - `event.pull([timeout:​ number], [name: string], ...): string, ...`  ​
-Pulls and returns the next available event from the queue, or waits until one becomes available. ​  +从队列中拉取下一个可用事件,或者等待可用事件出现。 ​  
-**timeout** - if passed the function will wait for a new event for this many seconds at maximum then returns ​`nil` if no event was queued during that time.\\ +**timeout** - 若指定了值,则函数会至多等待此秒数。超时后仍未出现可用事件,函数会返回`nil`\\ 
-**name** - an event pattern that will act as a filter. If given then only events that match this pattern will be returned. Can be `nil` in which case the event names will not be filtered. See `string.match` ​on how to use patterns.\\ +**name** - 目标事件的模式字符串,作为事件的过滤器。如果进行了指定则函数只会返回名称符合此模式的事件。值可以为`nil`,此时事件名称不会被过滤。模式字符串的使用可参考`string.match`函数。\\ 
-**...** - any number of parameters in the same order as defined by the [[component:​signals|signal]] that is expected. Those arguments will act as filters for the additional arguments returned by the signal. Direct equality is used to determine if the argument is equal to the given filter. Can be `nil` in which case this particular argument will not be filtered.\\ +**...** - 任意数量的参数,顺序需要与目标[[component:​signals|信号]]所定义的相同。它们会被作为过滤器来筛选信号返回的额外参数,判断方式为是否完全相等。值可以为`nil`,这样将不会过滤此参数。\\ 
-Filter example: ​  +筛选样例: ​  
-The `touch` ​signal ​(when a player clicks on a tier two or three screenhas the signature ​` screenX: number, screenY: number, playerName: string` ​  +`touch`信号(在玩家点击2级或3级显示器时触发)带有如下参数:` screenX: number, screenY: number, playerName: string`(点击处的X、Y坐标,进行点击的玩家ID) ​  
-To only pull clicks by player ​"​Steve" ​you'd do:   +若要仅拉取玩家"​Steve"​的点击,你需要使用: ​  
-  `local _, x, y = event.pull("​touch",​ nil, nil, "​Steve"​)` +  `local _, x, y = event.pull("​touch",​ nil, nil, "​Steve"​)` ​  
-- `event.pullFiltered([timeout:​ number], [filter: function]): string, ...` (Since ​1.5.9) +\\ 
-Pulls and returns the next available event from the queue, or waits until one becomes available but allows filtering by specifying filter function. +- `event.pullFiltered([timeout:​ number], [filter: function]): string, ...`(自1.5.9起添加)  ​ 
-**timeout** - if passed the function will wait for a new event for this many seconds at maximum then returns ​`nil` if no event was queued during that time.\\ +从队列中拉取并返回下一个可用事件,或者等待可用事件出现。支持以函数作为过滤器。  ​ 
-**filter** - if passed the function will use it as a filtering function of events. Allows for advanced filtering.+**timeout** - 若指定了值,则函数会至多等待此秒数。超时后仍未出现可用事件,则函数会返回`nil`\\ 
 +**filter** - 若指定了值,则此函数将会被作为事件的过滤器。让程序能够进行高级过滤。
  
-  Example:+样例:
  
 ```lua ```lua
Line 77: Line 79:
 end end
  
-local e = {event.pullFiltered(filter)} ​ -- We are pulling ​key_upkey_down ​and click events for unlimited amount of time. The filter will ensure that only events caused by players in allowedPlayers ​are pulled.+local e = {event.pullFiltered(filter)} ​ --程序将会不限时等待拉取key_upkey_downclick事件。过滤器会确保只拉取allowedPlayers表中的玩家触发的事件。
 ``` ```
  
-- `event.pullMultiple(...):​ ...` (Since ​1.5.9) +- `event.pullMultiple(...):​ ...`(自1.5.9起添加)  ​ 
-As its arguments ​`pullMultiple` ​accepts multiple event names to be pulled, allowing basic filtering of multiple events at once.+`pullMultiple`函数可接收多个要拉取的事件名称作为参数,同时支持基本的过滤功能。 ​  
 +\\
 - `event.onError(message:​ any)`  ​ - `event.onError(message:​ any)`  ​
-Global event callback error handler. If an event listener throws an error, we handle it in this function to avoid it bubbling into unrelated code (that only triggered the execution by calling ​`event.pull`). Per default, this logs errors into a file on the temporary file system. ​  +全局的异常处理函数,用于处理事件回调函数抛出的错误。若有事件侦听器抛出异常,此函数将会进行处理,以避免其影响到不相关的代码(指仅是调用了`events.pull`函数触发函数执行的代码)。默认情况下,此函数会将报错信息记录到临时文件系统中的文件。 ​  
-You can replace this function with your own if you want to handle event errors in a different way.+如果你想以其他方式处理事件报错,可以将此函数替换为自定义函数。 ​  
 +\\
 - `event.push(name:​ string[, ...])`  ​ - `event.push(name:​ string[, ...])`  ​
-This is only an alias to [[api:​computer|computer.pushSignal]]. This does not modify the arguments in any way. It seemed logical to add the alias to the event library because there is also an `event.pull` ​for signals.+此函数仅仅为[[api:​computer|computer.pushSignal]]的别名,并没有对参数进行任何修改。鉴于event(事件) API库中已经有了`event.pull`,添加此别名会更符合逻辑。
  
  
-===== Interrupts ​===== +===== 中断 ​===== 
-Starting In OpenOS 1.6.4 and later, interrupts have been cleaned up. The following two methods are now obsolete+OpenOS 1.6.4及更高版本,中断功能已经被删除。下列两个函数现在已经过时。
  
-- `event.shouldSoftInterrupt():​ boolean` ​(Since ​1.5.9 and removed in 1.6.4) +- `event.shouldSoftInterrupt():​ boolean`(自1.5.9起添加,在1.6.4被移除)  ​ 
-- `event.shouldInterrupt():​ boolean` ​ ​(Since ​1.5.9 and removed in 1.6.4)+- `event.shouldInterrupt():​ boolean`(自1.5.9起添加,在1.6.4被移除)
  
-Interrupts are a type of messaging intended to close or stop a process. In OpenOS ​the `computer.pullSignal()`, and thus any wrapper, generates 2 types of events.+中断是一类用于关闭或停止进程的消息。在OpenOS`computer.pullSignal()`函数及其封装会产生两种类型的事件。
  
-They are especially useful when `event.pull*()` ​is called without time limit and with a filter. In some cases this means that `event.pull*()` could be waiting indefinitely.+`event.pull*()`函数在指定了过滤器但不指定超时时间的情况下执行,一定情况下意味着无限期执行。这两种事件非常有用。
  
-Soft interrupts are an event signal generated by pressing ​`Ctrl+C`. The signal returns two fields, the event name `"​interrupted"​` ​and the computer uptime+软中断是在按下`Ctrl+C`时产生的事件信号。信号包含两个参数,事件名称`"​interrupted"​`和电脑运行时间。
  
-Hard interrupts are generated by pressing ​`Ctrl-Alt-C`. It forcibly exits the `event.pull*()` ​method by throwing a `"​interrupted"​` error.+硬中断在按下`Ctrl-Alt-C`时产生。它会通过抛出`"​interrupted"​`异常以强制退出`event.pull*()`函数。
  
-===== Basic event example ​===== +===== 简易事件处理样例 ​===== 
-Typically user scripts care about one or two events, and don't care to handle the rest. It is good to handle ​"​interrupted" ​for soft interrupts.+通常用户编写的脚本只会涉及一两个事件,不涉及其他事件的处理。建议将"​interrupted"​事件作为软件中断处理。
  
 ```lua ```lua
Line 118: Line 122:
 ``` ```
  
-===== General purpose event handler ​===== +===== 通用事件处理函数 ​===== 
-Here is a clever solution for providing a general purpose event handler. In this example the primary functionality uses the event id returned by `event.pull()` ​as a key for a table of callbacks, using metamethods to handle undefined events. Note that `event.pull` ​puts the program on hold until there is an event available.+此处提供了一个较好的通用事件处理函数。此样例的主要功能是以`event.pull()`函数返回的事件名称作为回调函数列表的键,用元方法来处理未定义事件。请注意`event.pull`函数会让程序进入等待状态,直到出现可用事件。
  
 ```lua ```lua
-local event = require "​event"​ -- load event table and store the pointer to it in event+local event = require "​event"​ --加载事件列表,将指向它们的指针存储到event变量中
  
-local char_space = string.byte("​ ") -- numerical representation of the space char +local char_space = string.byte("​ ") --用数字代替空格字符 
-local running = true -- state variable so the loop can terminate+local running = true --存储状态的变量,便于循环停止执行
  
 function unknownEvent() function unknownEvent()
-  -- do nothing if the event wasn't relevant+  --如果事件为无关事件,则不进行处理
 end end
  
--- table that holds all event handlers +--存储所有事件处理函数的列表 
--- in case no match can be found returns the dummy function ​unknownEvent+--会返回占位伪函数unknownEvent,以防无法匹配
 local myEventHandlers = setmetatable({},​ { __index = function() return unknownEvent end }) local myEventHandlers = setmetatable({},​ { __index = function() return unknownEvent end })
  
--- Example key-handler that simply sets running ​to false if the user hits space+--简易按键处理函数样例,当用户按下空格键时将running变量设为false
 function myEventHandlers.key_up(adress,​ char, code, playerName) function myEventHandlers.key_up(adress,​ char, code, playerName)
   if (char == char_space) then   if (char == char_space) then
Line 142: Line 146:
 end end
  
--- The main event handler as function to separate ​eventID ​from the remaining arguments+--主事件处理函数,将事件ID(eventID)从其他参数中分离出来
 function handleEvent(eventID,​ ...) function handleEvent(eventID,​ ...)
-  if (eventID) then -- can be nil if no event was pulled for some time +  if (eventID) then --如果一段时间内没有事件被拉取,值可能为nil 
-    myEventHandlers[eventID](...) -- call the appropriate event handler with all remaining arguments+    myEventHandlers[eventID](...) --调用对应的事件处理函数,并传递剩下的所有参数
   end   end
 end end
  
--- main event loop which processes all events, or sleeps if there is nothing to do+--主事件拉取循环,处理所有事件。在没有任务时会等待。
 while running do while running do
-  handleEvent(event.pull()) -- sleeps until an event is available, then process it+  handleEvent(event.pull()) --等待可用事件出现,然后进行处理
 end end
 ``` ```
  
  
-If you work in driver mode, you need to register the events instead, by either registering a global event handler like the one in the example above, or by registering each individual handler on its own. If you would write the example above to work in the background, the `while running do` loop would be replaced like this:+如果程序以驱动模式运作,你需要注册事件而不是拉取事件。你可以将所有事件注册到像上面样例一样的全局事件处理函数,也可以将每个事件注册到对应的处理函数。如果你希望上面的样例在后台运行,`while running do`循环需要替换为类似下面的代码:
  
 ```lua ```lua
-event.listen("​key_up",​ handleEvent) -- register ​handleEvent ​to be called on key_up ​then end the program+event.listen("​key_up",​ handleEvent) --注册handleEvent函数,使其在key_up事件发生时被调用,然后结束程序
 ``` ```
-It would also be possible to register ​`myEventHandlers.key_up` ​directly, in which case it would receive an additional parameter (the event name) as the first parameter.+也可以直接注册`myEventHandlers.key_up`,这样的话处理函数会额外收到一个参数(事件名称)作为第一个参数。
  
 目录 目录
 ----------- -----------
 {{page>​api:​contents:​zh&​noheader&​noeditbutton&​nouser&​nofooter}} {{page>​api:​contents:​zh&​noheader&​noeditbutton&​nouser&​nofooter}}