我希望更多地了解 nim 中的异步与 C 后端,并且对 Javascript 有一定的经验。 setTimeout
等功能可用于稍后执行函数。
示例:
setTimeout(() => console.log("Potato"), 1000)
nim 中的等效项是什么样的?
最佳答案
如果您想要快速解决方案,请选择 1)。如果您对异步基础知识感到好奇,请阅读整篇文章。
1) 使用异步语法 + SleepAsync
最简单的就是使用异步过程和 sleepasync
:
import std/asyncdispatch
proc afterX(wait: int) {.async.} =
await sleepAsync(wait)
echo "Stuff Happened"
let future: Future[void] = afterX(500)
... You can do more stuff in between getting the future and waiting for it ...
waitFor future
async
pragma 更改过程以返回 Future
无论它返回什么。在这种情况下什么也没有,所以void
。在您的“全局”同步上下文中,您可以这样 waitFor
.
请注意waitFor
与JS await
不相似。 JS 没有相当于它的东西,因为它没有对其执行的上下文的这种级别的访问权限。waitFor
用于等待任务在异步上下文之外完成,并且它将阻止线程这样做。尼姆的await
和JS的await
功能一样的是什么并且只能在异步过程中使用。
2) 没有异步语法:addTimer
Nim 有一个进程 setTimer如果您在文档中搜索与超时相关的关键字,您可能会偶然发现。
这就是我们想要的,但是使用非常不同的、更底层的语法,其功能几乎与 1 相同:
import std/asyncdispatch
let echoMe: Callback = proc(fd: AsyncFD): bool =
echo "Stuff Happened"
return true
addTimer(500, true, echoMe)
... You can do more stuff in between registering the callback and polling for it ...
poll()
AsyncFD
这是AsyncFileDescriptor
(或 Windows 上的句柄)。执行异步 IO 操作时,此参数将填充正在执行的 IO 操作的句柄。在这种情况下与我们无关,但了解它很有用。
AddTimer“注册”echoMe
proc 放在调度程序(某种事件循环)上以便稍后执行。
poll
然后获取该过程并执行它。
顺便说一句,与讨论无关:
addTimer
使用的 bool 值定义是否 echoMe
第一次执行后应从调度程序/事件循环中删除。所以false
意味着一遍又一遍地执行它,中间有时间延迟。
echoMe
返回的 bool 值还定义是否应从调度程序/事件循环中注销,但在每次执行后都会这样做。这仅在 addTimer
时才重要。被给予true
首先是它的 bool 值。所以true
来自echoMe
意思是“即使我被允许一遍又一遍地执行,现在就停止,从事件循环中注销我”。
为什么这两个相同?他们看起来不一样!
当 poll 获取一个过程时,它会阻塞线程,直到它可以获得任务或直到超时。这与 waitFor 非常相似。那是因为 waitFor 只是对 poll
的变相调用。在 while 循环中运行,直到 future.finished
bool 值从“false”翻转为“true”。
这两个都做了我们想要的事情,尽管异步使用更好的语法:
- 通过“任务调度程序”(
echoMe
pragma/async
)在队列上注册一个任务 (addTimer
) 以供稍后执行。 The dispatcher functions as a sort-of event-loop . - 让您可以同时做任何您想做的事情
- 强制您从队列中获取任务(
poll
、waitFor
)并隐式执行
主要区别在于,使用异步语法时,等待 N 毫秒是任务本身的一部分(通过 echoMe
在 sleepAsync
内),而使用 addTimer
则等待 N 毫秒。等待在轮询期间执行任务之前完成。
关于asynchronous - 如何在 nim 中执行有延迟的进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76958747/