muqsit/asynciterator

一个简化遍历迭代器任务的病毒

v1.1.4 2024-01-17 11:53 UTC

This package is auto-updated.

Last update: 2024-09-17 13:22:03 UTC


README

AsyncIterator 简化了编写异步迭代任务,例如遍历迭代器。

/** @var Plugin $plugin */
$handler = new AsyncIterator($plugin->getScheduler());

AsyncIterator::forEach 按插入顺序遍历 Iterator 类型并通知处理程序。可以通过向 AsyncIterator::forEach()::as() 传入一个签名为 function(TKey $key, TValue $value) : AsyncForeachResultClosure 来向 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