muqsit / asynciterator
一个简化遍历迭代器任务的病毒
v1.1.4
2024-01-17 11:53 UTC
Requires
- pocketmine/pocketmine-mp: ^5.0.0
README
AsyncIterator
简化了编写异步迭代任务,例如遍历迭代器。
/** @var Plugin $plugin */ $handler = new AsyncIterator($plugin->getScheduler());
AsyncIterator::forEach
按插入顺序遍历 Iterator
类型并通知处理程序。可以通过向 AsyncIterator::forEach()::as()
传入一个签名为 function(TKey $key, TValue $value) : AsyncForeachResult
的 Closure
来向 forEach
任务添加处理程序。
$handler->forEach(new ArrayIterator([1, 2])) ->as(function(int $key, int $value) : AsyncForeachResult{ echo "First ", $value; return AsyncForeachResult::CONTINUE(); }) ->as(function(int $key, int $value) : AsyncForeachResult{ echo "Second ", $value; return AsyncForeachResult::CONTINUE(); });
First 1
Second 1
First 2
Second 2
默认情况下,AsyncIterator::forEach
在每个 tick 上遍历 10 个条目。这可以通过覆盖方法的默认参数值来更改。
$entries_per_tick = 4; $sleep_time = 1; // in ticks AsyncIterator::forEach(new InfiniteIterator(new ArrayIterator([1, 2, 3])), $entries_per_tick, $sleep_time) ->as(function(int $key, int $value) : AsyncForeachResult{ echo $value, ", "; return AsyncForeachResult::CONTINUE(); });
# First Tick:
1, 2, 3, 1
# Second Tick:
2, 3, 1, 2
...
当 foreach 任务成功完成后,会触发完成监听器。这是通过传递给 AsyncIterator::forEach
的迭代器的 Iterator::valid()
返回值(即 $completed = !Iterator::valid()
)来确定的。
$handler->forEach(new ArrayIterator([1, 2, 3])) ->as(function(int $key, int $value) : AsyncForeachResult{ echo $value; return AsyncForeachResult::CONTINUE(); }) ->onCompletion(function() : void{ echo "Completed"; })
处理程序可以通过返回 AsyncForeachResult::CONTINUE()
、AsyncForeachResult::INTERRUPT()
或 AsyncForeachResult::CANCEL()
分别继续、中断或取消遍历。当中断时,forEach
任务将不再遍历迭代器,并立即通知中断监听器。然而,当取消时,forEach
任务将不会通知任何监听器,并立即销毁任务。
$handler->forEach(new ArrayIterator([1, 2, 3])) ->as(function(int $key, int $value) : AsyncForeachResult{ echo $value; return $value === 2 ? AsyncForeachResult::INTERRUPT() : AsyncForeachResult::CONTINUE(); }) ->onCompletion(function() : void{ echo "Completed"; }) ->onInterruption(function() : void{ echo "Interrupted"; });
1
2
Interrupted
$handler->forEach(new ArrayIterator([1, 2, 3])) ->as(function(int $key, int $value) : AsyncForeachResult{ echo $value; return AsyncForeachResult::CONTINUE(); }) ->onCompletion(function() : void{ echo "Completed"; }) ->onInterruption(function() : void{ echo "Interrupted"; });
1
2
3
Completed
forEach
任务的中断也可以通过在外部(处理程序外部)调用 forEach
返回值的 interrupt()
方法来实现。
$foreach_task = $handler->forEach(new ArrayIterator([1, 2, 3])) ->as(function(int $key, int $value) : AsyncForeachResult{ echo $value; return AsyncForeachResult::CONTINUE(); }) ->onCompletion(function() : void{ echo "Completed"; }) ->onInterruption(function() : void{ echo "Interrupted"; }); TaskScheduler::scheduleDelayedTask(function() use($foreach_task) : void{ $foreach_task->interrupt(); }, ticks: 2);
1
2
Interrupted
通过在 forEach
返回值上调用 cancel()
方法,可以取消 forEach
任务,导致不会通知任何中断或完成监听器。$foreach_task = $handler->forEach(new ArrayIterator([1, 2, 3])) ->as(function(int $key, int $value) : AsyncForeachResult{ echo $value; return AsyncForeachResult::CONTINUE(); }) ->onCompletion(function() : void{ echo "Completed"; }) ->onInterruption(function() : void{ echo "Interrupted"; }); TaskScheduler::scheduleDelayedTask(function() use($foreach_task) : void{ $foreach_task->cancel(); }, ticks: 2);
1
2