Spread spawning across multiple frames?

Ok, below is my final solution. It includes 3 new nodes:

AsyncForLoop: standard loop using an async task broadcasting each loop
AsyncDelayForLoop: inserts a delay between each loop
AsyncBurstForLoop: inserts a delay between X loops (e.g. every 3 index insert a delay)

AsyncForLoop.cpp

#include "AsyncLoops/Public/AsyncForLoop.h"

void UAsyncForLoop::Activate()
{
	if ( Delay > 0.f ) {
		DelayLoop();
		return;
	}

	for ( int32 Index = FirstIndex; Index <= LastIndex; ++Index ) {
		LoopBody.Broadcast( Index );
	}

	Completed.Broadcast( 0 );

	SetReadyToDestroy();
}

void UAsyncForLoop::DelayLoop()
{
	if ( ! IsValid( World ) ) {
		Completed.Broadcast( 0 );

		SetReadyToDestroy();
		return;
	}

	World->GetTimerManager().ClearTimer( DelayTimerHandle );

	LoopBody.Broadcast( CurrentIndex );

	if ( CurrentIndex == LastIndex ) {
		Completed.Broadcast( 0 );

		SetReadyToDestroy();
		return;
	}

	++CurrentIndex;

	if ( Burst > 1 ) {
		for ( int32 Index = FirstIndex; Index <= ( Burst - 1 ); ++Index ) {
			LoopBody.Broadcast( CurrentIndex );

			++CurrentIndex;

			if ( CurrentIndex == LastIndex ) {
				Completed.Broadcast( 0 );

				SetReadyToDestroy();
				return;
			}
		}
	}

	World->GetTimerManager().SetTimer( DelayTimerHandle, this, &UAsyncForLoop::DelayLoop, Delay, false, Delay );
}

UAsyncForLoop* UAsyncForLoop::AsyncForLoop(
	int FirstIndex,
	int LastIndex
) {
	UAsyncForLoop* BlueprintNode = NewObject<UAsyncForLoop>();

	BlueprintNode->FirstIndex = FirstIndex;
	BlueprintNode->LastIndex = LastIndex;

	return BlueprintNode;
}

UAsyncForLoop* UAsyncForLoop::AsyncDelayForLoop(
	UObject* WorldContextObject,
	int FirstIndex,
	int LastIndex,
	float Delay
) {
	UAsyncForLoop* BlueprintNode = NewObject<UAsyncForLoop>();

	if ( IsValid( WorldContextObject ) ) {
		BlueprintNode->World = WorldContextObject->GetWorld();
	}

	BlueprintNode->FirstIndex = FirstIndex;
	BlueprintNode->LastIndex = LastIndex;
	BlueprintNode->Delay = Delay;

	return BlueprintNode;
}

UAsyncForLoop* UAsyncForLoop::AsyncBurstForLoop(
	UObject* WorldContextObject,
	int FirstIndex,
	int LastIndex,
	float Delay,
	int Burst
) {
	UAsyncForLoop* BlueprintNode = NewObject<UAsyncForLoop>();

	if ( IsValid( WorldContextObject ) ) {
		BlueprintNode->World = WorldContextObject->GetWorld();
	}

	BlueprintNode->FirstIndex = FirstIndex;
	BlueprintNode->LastIndex = LastIndex;
	BlueprintNode->Delay = Delay;
	BlueprintNode->Burst = Burst;

	return BlueprintNode;
}

AsyncForLoop.h

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "Delegates/IDelegateInstance.h"
#include "AsyncForLoop.generated.h"

UCLASS( Blueprintable )
class ASYNCLOOPS_API UAsyncForLoop : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()

public:
	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FOAsyncForLoopSignature, int, Index );

	virtual void Activate() override;		

	UPROPERTY( BlueprintAssignable, Category = "AsyncLoops" )
		FOAsyncForLoopSignature LoopBody;

	UPROPERTY( BlueprintAssignable, Category = "AsyncLoops" )
		FOAsyncForLoopSignature Completed;

	UFUNCTION( BlueprintCallable, meta = ( BlueprintInternalUseOnly = "true" ), Category = "AsyncLoops", DisplayName = "Async For Loop" )
		static UAsyncForLoop* AsyncForLoop(
			int FirstIndex = 0,
			int LastIndex = 0
		);

	UFUNCTION( BlueprintCallable, meta = ( BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject" ), Category = "AsyncLoops", DisplayName = "Async Delay For Loop" )
		static UAsyncForLoop* AsyncDelayForLoop(
			UObject* WorldContextObject,
			int FirstIndex = 0,
			int LastIndex = 0,
			float Delay = 0.01f
		);

	UFUNCTION( BlueprintCallable, meta = ( BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject" ), Category = "AsyncLoops", DisplayName = "Async Burst For Loop" )
		static UAsyncForLoop* AsyncBurstForLoop(
			UObject* WorldContextObject,
			int FirstIndex = 0,
			int LastIndex = 0,
			float Delay = 0.1f,
			int Burst = 5
		);

protected:
	class UWorld* World = nullptr;
	int FirstIndex = 0;
	int LastIndex = 0;
	int CurrentIndex = 0;
	float Delay = 0.f;
	int Burst = 0;
	FTimerHandle DelayTimerHandle;

	UFUNCTION()
		void DelayLoop();
};

It’s probably not perfect and there’s probably better ways to code this, but for now works great.