Transpilers/Keywords/Await.psx.ps1
<# .SYNOPSIS awaits asynchronous operations .DESCRIPTION awaits the result of a task. .EXAMPLE .>PipeScript -ScriptBlock { await $Websocket.SendAsync($SendSegment, 'Binary', $true, [Threading.CancellationToken]::new($false)) } .EXAMPLE .>PipeScript -ScriptBlock { $receiveResult = await $Websocket.ReceiveAsync($receiveSegment, [Threading.CancellationToken]::new($false)) } #> [ValidateScript({ $CommandAst = $_ $CommandAst.CommandElements -and $CommandAst.CommandElements[0].Value -eq 'await' })] param( [Parameter(Mandatory,ValueFromPipeline)] [Management.Automation.Language.CommandAST] $CommandAst ) process { if ($CommandAst.CommandElements.Count -lt 2) { Write-Error "await what?" return } if ($CommandAst.CommandElements[0].Value -ne 'await') { Write-Error "not await" return } if ($CommandAst.CommandElements[1] -isnot [Management.Automation.Language.InvokeMemberExpressionAst]) { Write-Error "await must be followed by an invocation expression" return } # Note: This is one of those cases where version targeting might be handy. # older versions of PowerShell (I believe -lt 4.0) will not handle task returns correctly without help. [Timespan]$awaitTimeout = '00:00:10' [Timespan]$awaitSleep = 7 $newScript = @( '[DateTime]$awaitTimeout = [DateTime]::Now + "' + "$awaitTimeout" + '"' '[TimeSpan]$awaitSleep = "' + "$awaitSleep" + '"' '$awaitTask = ' + "$($commandAst.CommandElements[1].Extent.ToString())" { while (!$awaitTask.IsCompleted -and [DateTime]::Now -lt $awaitTimeout) { Start-Sleep -Milliseconds $awaitSleep.TotalMilliseconds } if ($awaitTask.IsCompleted -and $null -ne $awaitTask.Result) { $awaitTask.Result } elseif ($awaitTask.IsCompleted -and $awaitTask.Exception) { if ($awaitTask.Exception.InnerExceptions) { $awaitTask.Exception.InnerExceptions } else { $awaitTask.Exception } } } ) -join [Environment]::NewLine if ($CommandAst.IsAssigned) { $newScript = "`$($newScript)" } [ScriptBlock]::create($newScript) } |